from django.core.management.base import BaseCommand
from app_files.models import *


class Command(BaseCommand):
    help = "Contrôle l'intégrité des nouvelles tables relationnelles sans se baser sur les anciens champs legacy."

    def add_arguments(self, parser):
        parser.add_argument(
            "--verbose-lines",
            action="store_true",
            help="Affiche le détail des lignes document contrôlées.",
        )

    def handle(self, *args, **options):
        errors = []
        warnings = []
        ok_count = 0

        self.stdout.write("Diagnostic nouvelles tables CRM : contrôle sans champs legacy")
        self.stdout.write("----------------------------------------------------------")

        # company_contacts
        for relation in models_company_contacts.objects.select_related("company", "contact").all():
            if not relation.company_id or not models_companies.objects.filter(id_company=relation.company_id).exists():
                errors.append(f"company_contact orphan company | company_id={relation.company_id} | contact_id={relation.contact_id}")
            elif not relation.contact_id or not models_contacts.objects.filter(id_contact=relation.contact_id).exists():
                errors.append(f"company_contact orphan contact | company_id={relation.company_id} | contact_id={relation.contact_id}")
            else:
                ok_count += 1

        # company_projects
        for relation in models_company_projects.objects.select_related("company", "project").all():
            if not relation.company_id or not models_companies.objects.filter(id_company=relation.company_id).exists():
                errors.append(f"company_project orphan company | company_id={relation.company_id} | project_id={relation.project_id}")
            elif not relation.project_id or not models_projects.objects.filter(id_project=relation.project_id).exists():
                errors.append(f"company_project orphan project | company_id={relation.company_id} | project_id={relation.project_id}")
            else:
                ok_count += 1

        # company_addresses
        for relation in models_company_addresses.objects.select_related("company", "address").all():
            if not relation.company_id or not models_companies.objects.filter(id_company=relation.company_id).exists():
                errors.append(f"company_address orphan company | company_id={relation.company_id} | address_id={relation.address_id}")
            elif not relation.address_id or not models_addresses.objects.filter(id_address=relation.address_id).exists():
                errors.append(f"company_address orphan address | company_id={relation.company_id} | address_id={relation.address_id}")
            else:
                ok_count += 1

        # project_sales_documents
        for relation in models_project_sales_documents.objects.select_related("project", "sales_document").all():
            if not relation.project_id or not models_projects.objects.filter(id_project=relation.project_id).exists():
                errors.append(f"project_sales_document orphan project | project_id={relation.project_id} | sales_document_id={relation.sales_document_id}")
            elif not relation.sales_document_id or not models_sales_documents.objects.filter(id_sales_documents=relation.sales_document_id).exists():
                errors.append(f"project_sales_document orphan document | project_id={relation.project_id} | sales_document_id={relation.sales_document_id}")
            else:
                ok_count += 1

        # interaction_companies
        for relation in models_interaction_companies.objects.select_related("interaction", "company").all():
            if not relation.interaction_id or not models_interactions.objects.filter(id_interaction=relation.interaction_id).exists():
                errors.append(f"interaction_company orphan interaction | interaction_id={relation.interaction_id} | company_id={relation.company_id}")
            elif not relation.company_id or not models_companies.objects.filter(id_company=relation.company_id).exists():
                errors.append(f"interaction_company orphan company | interaction_id={relation.interaction_id} | company_id={relation.company_id}")
            else:
                ok_count += 1

        # sales document lines: dynamic mode.
        # Real documents must have at least one line and their line numbers/positions
        # must be sequential from 1 to N. N can be lower or higher than 25.
        for doc in models_sales_documents.objects.exclude(id_sales_documents='0'):
            line_qs = models_sales_document_lines.objects.filter(sales_document=doc).order_by('sales_documents_line_position', 'id_sales_document_line')
            line_count = line_qs.count()
            if line_count < 1:
                errors.append(f"document line count invalid | doc={doc.id_sales_documents} | expected>=1 | found={line_count}")
                continue

            seen_numbers = set()
            seen_positions = set()
            for line in line_qs:
                line_number = int(line.sales_documents_line_number or 0)
                line_position = int(line.sales_documents_line_position or 0)
                seen_numbers.add(line_number)
                seen_positions.add(line_position)

                if options.get("verbose_lines"):
                    self.stdout.write(
                        f"line ok check | doc={doc.id_sales_documents} | number={line_number} | position={line_position}"
                    )

            expected = set(range(1, line_count + 1))
            if seen_numbers != expected:
                errors.append(f"document line numbers invalid | doc={doc.id_sales_documents} | expected=1..{line_count} | found={sorted(seen_numbers)}")
            elif seen_positions != expected:
                errors.append(f"document line positions invalid | doc={doc.id_sales_documents} | expected=1..{line_count} | found={sorted(seen_positions)}")
            else:
                ok_count += 1

        # deposits: linked document must exist. Empty deposit table is valid.
        for deposit in models_sales_document_deposits.objects.select_related("sales_document").all():
            if not deposit.sales_document_id or not models_sales_documents.objects.filter(id_sales_documents=deposit.sales_document_id).exists():
                errors.append(f"deposit orphan document | deposit_id={deposit.sales_documents_deposit_id} | doc={deposit.sales_document_id}")
            else:
                ok_count += 1

        self.stdout.write("")
        self.stdout.write(f"Contrôles OK : {ok_count}")
        self.stdout.write(f"Avertissements : {len(warnings)}")
        self.stdout.write(f"Erreurs : {len(errors)}")

        if warnings:
            self.stdout.write("")
            self.stdout.write("AVERTISSEMENTS")
            for warning in warnings:
                self.stdout.write(f"- {warning}")

        if errors:
            self.stdout.write("")
            self.stdout.write("ERREURS D'INTÉGRITÉ")
            for error in errors:
                self.stdout.write(f"- {error}")
            self.stdout.write("")
            self.stdout.write(self.style.ERROR("Résultat : intégrité des nouvelles tables non validée."))
            return

        self.stdout.write("")
        self.stdout.write(self.style.SUCCESS("Résultat : nouvelles tables relationnelles cohérentes."))
