import json
from datetime import date, datetime

from fastapi import APIRouter, Depends, HTTPException
from sqlalchemy.orm import Session, selectinload

from app.database import get_db
from app.deps import require_permission
from app.models import EnquiryForm, FormField, FormFieldOption, FormSubmission, User
from app.schemas import EnquiryIn, FormIn, FormOut, FormSubmitIn, FormSubmissionOut
from app.routers.crm import _sync_client_from_enquiry
from app.utils import next_public_id
from app.models import Enquiry

router = APIRouter(tags=["forms"])


def serialize_form(form: EnquiryForm) -> FormOut:
    return FormOut(
        id=form.id,
        name=form.name,
        description=form.description,
        is_active=form.is_active,
        fields=[
            {
                "id": field.id,
                "label": field.label,
                "field_key": field.field_key,
                "field_type": field.field_type,
                "is_required": field.is_required,
                "sort_order": field.sort_order,
                "options": [opt.label for opt in field.options],
            }
            for field in sorted(form.fields, key=lambda item: item.sort_order)
        ],
    )


@router.get("/forms", response_model=list[FormOut])
def list_forms(db: Session = Depends(get_db), _: User = Depends(require_permission("form.view"))):
    rows = db.query(EnquiryForm).options(selectinload(EnquiryForm.fields).selectinload(FormField.options)).all()
    return [serialize_form(row) for row in rows]


@router.post("/forms", response_model=FormOut)
def create_form(payload: FormIn, db: Session = Depends(get_db), actor: User = Depends(require_permission("form.create"))):
    form = EnquiryForm(name=payload.name, description=payload.description, is_active=payload.is_active, created_by_id=actor.id)
    form.fields = [
        FormField(
            label=field.label,
            field_key=field.field_key,
            field_type=field.field_type,
            is_required=field.is_required,
            sort_order=field.sort_order,
            options=[FormFieldOption(label=opt, value=opt) for opt in field.options],
        )
        for field in payload.fields
    ]
    db.add(form)
    db.commit()
    form = db.query(EnquiryForm).options(selectinload(EnquiryForm.fields).selectinload(FormField.options)).filter(EnquiryForm.id == form.id).first()
    return serialize_form(form)


@router.get("/form-submissions", response_model=list[FormSubmissionOut])
def list_submissions(db: Session = Depends(get_db), _: User = Depends(require_permission("form.view"))):
    rows = db.query(FormSubmission).order_by(FormSubmission.id.desc()).all()
    return [
        FormSubmissionOut(
            id=row.id,
            form_id=row.form_id,
            payload=json.loads(row.payload),
            enquiry_id=row.enquiry_id,
            client_id=row.client_id,
            created_at=row.created_at,
        )
        for row in rows
    ]


@router.post("/forms/{form_id}/submit", response_model=FormSubmissionOut)
def submit_form(form_id: int, payload: FormSubmitIn, db: Session = Depends(get_db), _: User = Depends(require_permission("enquiry.create"))):
    form = db.query(EnquiryForm).filter(EnquiryForm.id == form_id).first()
    if form is None:
        raise HTTPException(status_code=404, detail="Form not found")
    data = payload.payload
    event_date = data.get("event_date")
    parsed_date = None
    if event_date:
        parsed_date = date.fromisoformat(str(event_date)[:10])
    enquiry_payload = EnquiryIn(
        client_name=data.get("client_name") or data.get("name") or "Unknown",
        company_name=data.get("company_name"),
        phone=str(data.get("phone") or "0000000000"),
        email=data.get("email"),
        event_type=data.get("event_type"),
        event_date=parsed_date,
        district=data.get("district"),
        city=data.get("city"),
        venue=data.get("venue"),
        requirements=data.get("requirements"),
        lead_source=data.get("lead_source") or "Form",
        booking_channel="Web Form",
    )
    client = _sync_client_from_enquiry(db, enquiry_payload)
    enquiry_data = enquiry_payload.model_dump(exclude={"company_name"})
    enquiry_data["client_id"] = client.id
    enquiry = Enquiry(public_id=next_public_id(db, Enquiry, "ENQ"), **enquiry_data)
    db.add(enquiry)
    db.flush()
    row = FormSubmission(
        form_id=form.id,
        payload=json.dumps(data, default=str),
        enquiry_id=enquiry.id,
        client_id=enquiry.client_id,
        created_at=datetime.utcnow(),
    )
    db.add(row)
    db.commit()
    db.refresh(row)
    return FormSubmissionOut(
        id=row.id,
        form_id=row.form_id,
        payload=data,
        enquiry_id=row.enquiry_id,
        client_id=row.client_id,
        created_at=row.created_at,
    )
