"use client";

import * as React from "react";
import { useEffect, useMemo, useState } from "react";
import { useMutation } from "@tanstack/react-query";
import { toast } from "sonner";
import { Icons } from "@/components/icons";
import { Button } from "@/components/ui/button";
import {
  Select,
  SelectContent,
  SelectItem,
  SelectTrigger,
  SelectValue,
} from "@/components/ui/select";
import {
  Sheet,
  SheetContent,
  SheetDescription,
  SheetFooter,
  SheetHeader,
  SheetTitle,
} from "@/components/ui/sheet";
import { useAppForm, useFormFields } from "@/components/ui/tanstack-form";
import { createLeadMutation, updateLeadMutation } from "../api/mutations";
import type { LeadReferenceData, LeadSummary } from "../api/types";
import { leadFormSchema } from "../schemas/lead.schema";

type LeadFormValues = Record<string, unknown> & {
  branchId: string | null;
  customerId: string | null;
  contactId: string | null;
  description: string | null;
  projectName: string | null;
  projectLocation: string | null;
  leadChannel: string | null;
  productType: string | null;
  priority: string | null;
  estimatedValue: number | null;
  awarenessId: string | null;
  status: string;
  followupStatus: string | null;
  lostReason: string | null;
  outcome: "open" | "won" | "lost";
  ownerMarketingUserId: string | null;
};

function getNewJobStatusId(referenceData: LeadReferenceData) {
  return (
    referenceData.statuses.find((item) => item.code === "new_job")?.id ??
    referenceData.statuses[0]?.id ??
    ""
  );
}

function toDefaultValues(
  lead: LeadSummary | undefined,
  referenceData: LeadReferenceData,
): LeadFormValues {
  return {
    branchId: lead?.branchId ?? referenceData.branches[0]?.id ?? null,
    customerId: lead?.customerId ?? null,
    contactId: lead?.contactId ?? null,
    description: lead?.description ?? null,
    projectName: lead?.projectName ?? null,
    projectLocation: lead?.projectLocation ?? null,
    leadChannel: lead?.leadChannel ?? null,
    productType: lead?.productType ?? referenceData.productTypes[0]?.id ?? null,
    priority: lead?.priority ?? referenceData.priorities[0]?.id ?? null,
    estimatedValue: lead?.estimatedValue ?? null,
    awarenessId: lead?.awarenessId ?? referenceData.awarenesses[0]?.id ?? null,
    status: lead?.status ?? getNewJobStatusId(referenceData),
    followupStatus: lead?.followupStatus ?? null,
    lostReason: lead?.lostReason ?? null,
    outcome:
      lead?.outcome === "won" || lead?.outcome === "lost"
        ? lead.outcome
        : "open",
    ownerMarketingUserId: lead?.ownerMarketingUserId ?? null,
  };
}

export function LeadForm({
  open,
  onOpenChange,
  referenceData,
  lead,
}: {
  open: boolean;
  onOpenChange: (open: boolean) => void;
  referenceData: LeadReferenceData;
  lead?: LeadSummary;
}) {
  const isEdit = Boolean(lead);
  const [selectedCustomerId, setSelectedCustomerId] = useState(
    lead?.customerId ?? "",
  );
  const defaultValues = useMemo(
    () => toDefaultValues(lead, referenceData),
    [lead, referenceData],
  );
  const {
    FormCurrencyField,
    FormSelectField,
    FormTextField,
    FormTextareaField,
  } = useFormFields<LeadFormValues>();

  const createMutation = useMutation({
    ...createLeadMutation,
    onSuccess: () => {
      toast.success("Lead created successfully");
      onOpenChange(false);
    },
    onError: (error) => {
      toast.error(
        error instanceof Error ? error.message : "Unable to create lead",
      );
    },
  });

  const updateMutation = useMutation({
    ...updateLeadMutation,
    onSuccess: () => {
      toast.success("Lead updated successfully");
      onOpenChange(false);
    },
    onError: (error) => {
      toast.error(
        error instanceof Error ? error.message : "Unable to update lead",
      );
    },
  });

  const contactsForCustomer = referenceData.contacts.filter(
    (contact) => contact.customerId === selectedCustomerId,
  );

  const form = useAppForm({
    defaultValues,
    validators: {
      onSubmit: leadFormSchema,
    },
    onSubmit: async ({ value }) => {
      const payload = {
        branchId: value.branchId || null,
        customerId: value.customerId || null,
        contactId: value.contactId || null,
        description: value.description || null,
        projectName: value.projectName || null,
        projectLocation: value.projectLocation || null,
        leadChannel: value.leadChannel || null,
        productType: value.productType || null,
        priority: value.priority || null,
        estimatedValue: value.estimatedValue ?? null,
        awarenessId: value.awarenessId || null,
        status: value.status,
        followupStatus: value.followupStatus || null,
        lostReason: value.lostReason || null,
        outcome: value.outcome,
        ownerMarketingUserId: value.ownerMarketingUserId || null,
      };

      if (isEdit && lead) {
        await updateMutation.mutateAsync({ id: lead.id, values: payload });
        return;
      }

      await createMutation.mutateAsync(payload);
    },
  });

  useEffect(() => {
    if (!open) {
      return;
    }

    form.reset(defaultValues);
    setSelectedCustomerId(defaultValues.customerId ?? "");
  }, [defaultValues, form, open]);

  const isPending = createMutation.isPending || updateMutation.isPending;

  return (
    <Sheet open={open} onOpenChange={onOpenChange}>
      <SheetContent className="flex w-full flex-col sm:max-w-3xl">
        <SheetHeader>
          <SheetTitle>{isEdit ? "Edit Lead" : "Create Lead"}</SheetTitle>
          <SheetDescription>
            Capture marketing lead information before assignment to the sales
            workspace.
          </SheetDescription>
        </SheetHeader>

        <div className="flex-1 overflow-auto">
          <form.AppForm>
            <form.Form id="lead-form" className="grid gap-4 md:grid-cols-2">
              <form.AppField
                name="customerId"
                children={(field) => (
                  <field.FieldSet>
                    <field.Field>
                      <field.FieldLabel>Customer</field.FieldLabel>
                      <Select
                        value={
                          typeof field.state.value === "string"
                            ? field.state.value
                            : "__none__"
                        }
                        onValueChange={(nextValue) => {
                          const customerId =
                            nextValue === "__none__" ? null : nextValue;
                          field.handleChange(customerId);
                          field.handleBlur();
                          setSelectedCustomerId(customerId ?? "");
                          form.setFieldValue("contactId", null);
                        }}
                      >
                        <SelectTrigger aria-label="Customer">
                          <SelectValue placeholder="Select customer" />
                        </SelectTrigger>
                        <SelectContent>
                          <SelectItem value="__none__">
                            No customer selected
                          </SelectItem>
                          {referenceData.customers.map((customer) => (
                            <SelectItem key={customer.id} value={customer.id}>
                              {customer.name} ({customer.code})
                            </SelectItem>
                          ))}
                        </SelectContent>
                      </Select>
                    </field.Field>
                    <field.FieldError />
                  </field.FieldSet>
                )}
              />

              <form.AppField
                name="contactId"
                children={(field) => (
                  <field.FieldSet>
                    <field.Field>
                      <field.FieldLabel>Contact</field.FieldLabel>
                      <Select
                        value={
                          typeof field.state.value === "string"
                            ? field.state.value
                            : "__none__"
                        }
                        onValueChange={(nextValue) => {
                          field.handleChange(
                            nextValue === "__none__" ? null : nextValue,
                          );
                          field.handleBlur();
                        }}
                      >
                        <SelectTrigger aria-label="Contact">
                          <SelectValue placeholder="Select contact" />
                        </SelectTrigger>
                        <SelectContent>
                          <SelectItem value="__none__">
                            No contact selected
                          </SelectItem>
                          {contactsForCustomer.map((contact) => (
                            <SelectItem key={contact.id} value={contact.id}>
                              {contact.name}
                              {contact.isPrimary ? " (Primary)" : ""}
                            </SelectItem>
                          ))}
                        </SelectContent>
                      </Select>
                    </field.Field>
                    <field.FieldError />
                  </field.FieldSet>
                )}
              />
              <FormSelectField
                name="branchId"
                label="Branch"
                options={referenceData.branches.map((branch) => ({
                  value: branch.id,
                  label: branch.name,
                }))}
              />
              <FormTextField name="projectName" label="Project Name" />
              <FormTextField name="projectLocation" label="Project Location" />

              <FormSelectField
                name="productType"
                label="Product Type"
                options={referenceData.productTypes.map((item) => ({
                  value: item.id,
                  label: item.label,
                }))}
              />
              <FormSelectField
                name="leadChannel"
                label="Lead Source"
                options={referenceData.leadChannels.map((item) => ({
                  value: item.id,
                  label: item.label,
                }))}
              />
              <FormSelectField
                name="awarenessId"
                label="Awareness"
                options={referenceData.awarenesses.map((item) => ({
                  value: item.id,
                  label: item.label,
                }))}
              />

              <FormSelectField
                name="priority"
                label="Priority"
                options={referenceData.priorities.map((item) => ({
                  value: item.id,
                  label: item.label,
                }))}
              />

              <FormCurrencyField
                name="estimatedValue"
                label="Estimated Value"
                currencyLabel="THB"
              />

              <FormSelectField
                name="followupStatus"
                label="Follow-up Status"
                options={referenceData.followupStatuses.map((item) => ({
                  value: item.id,
                  label: item.label,
                }))}
              />

              {isEdit ? (
                <>
                  <FormSelectField
                    name="status"
                    label="Status"
                    options={referenceData.statuses.map((item) => ({
                      value: item.id,
                      label: item.label,
                    }))}
                  />
                  <FormSelectField
                    name="lostReason"
                    label="Lost Reason"
                    options={referenceData.lostReasons.map((item) => ({
                      value: item.id,
                      label: item.label,
                    }))}
                  />
                  <FormSelectField
                    name="ownerMarketingUserId"
                    label="Marketing Owner"
                    options={referenceData.assignableUsers.map((user) => ({
                      value: user.id,
                      label: user.name,
                    }))}
                  />
                </>
              ) : null}

              <div className="md:col-span-2">
                <FormTextareaField
                  name="description"
                  label="Description"
                  size="md"
                />
              </div>
            </form.Form>
          </form.AppForm>
        </div>

        <SheetFooter>
          <Button
            variant="outline"
            onClick={() => onOpenChange(false)}
            disabled={isPending}
          >
            Cancel
          </Button>
          <Button type="submit" form="lead-form" isLoading={isPending}>
            <Icons.add className="mr-2 h-4 w-4" />
            {isEdit ? "Update Lead" : "Create Lead"}
          </Button>
        </SheetFooter>
      </SheetContent>
    </Sheet>
  );
}

export function LeadFormTrigger({
  referenceData,
}: {
  referenceData: LeadReferenceData;
}) {
  const [open, setOpen] = React.useState(false);

  return (
    <>
      <Button onClick={() => setOpen(true)}>
        <Icons.add className="mr-2 h-4 w-4" />
        Add Lead
      </Button>
      <LeadForm
        open={open}
        onOpenChange={setOpen}
        referenceData={referenceData}
      />
    </>
  );
}
