"use client";

import * as React from "react";

import { format } from "date-fns";
import { CalendarIcon, Pencil, UserPlus } from "lucide-react";
import {
  Controller,
  type FieldErrors,
  type UseFormReturn,
} from "react-hook-form";

import { FormPageHeader, FormSaveBar, FormSelect } from "@/app/dashboard/_components/form";
import { ErrorBanner } from "@/components/shared/error-banner";
import { Button } from "@/components/ui/button";
import { Calendar } from "@/components/ui/calendar";
import { Checkbox } from "@/components/ui/checkbox";
import {
  InputGroup,
  InputGroupInput,
} from "@/components/ui/input-group";
import { Input } from "@/components/ui/input";
import { Popover, PopoverContent, PopoverTrigger } from "@/components/ui/popover";
import { Separator } from "@/components/ui/separator";
import { cn } from "@/lib/utils";

import {
  ACCOUNT_TYPES,
  COUNTRIES,
  CUSTOMER_STATUSES,
  EMAIL_VERIFIED_OPTIONS,
  PRICE_PLANS,
  TIMEZONES,
} from "./constants";
import { FormField } from "./form-field";
import { FormSection } from "./form-section";
import { PhoneInput } from "./phone-input";
import type { CustomerCreateFormValues, CustomerSharedFormValues, CustomerUpdateFormValues } from "./schema";
import {
  CUSTOMER_LIST_HREF,
  useCustomerCreateForm,
  useCustomerUpdateForm,
  type CustomerCreateSubmitOptions,
} from "./use-customer-form";

function sanitizeSubdomain(value: string) {
  let input = value.toLowerCase().replace(/[^a-z0-9-]/g, "");
  if (input.startsWith("-")) input = input.slice(1);
  if (input.endsWith("-")) input = input.slice(0, -1);
  return input;
}

type CustomerFormProps = {
  mode?: "create" | "update";
  customerId?: number;
  initial?: CustomerUpdateFormValues;
  initialErrorMessage?: string | null;
  createSubmitOptions?: CustomerCreateSubmitOptions;
  listHref?: string;
  showMembership?: boolean;
};

function DatePickerField({
  value,
  onChange,
  placeholder = "Select date",
}: {
  value: string;
  onChange: (value: string) => void;
  placeholder?: string;
}) {
  const date = value ? new Date(value) : undefined;

  return (
    <Popover>
      <PopoverTrigger asChild>
        <Button
          type="button"
          variant="outline"
          className={cn("h-9 w-full justify-start font-normal", !value && "text-muted-foreground")}
        >
          <CalendarIcon className="size-4" />
          {date ? format(date, "yyyy-MM-dd") : placeholder}
        </Button>
      </PopoverTrigger>
      <PopoverContent className="w-auto p-0" align="start">
        <Calendar
          mode="single"
          selected={date}
          onSelect={(d) => onChange(d ? format(d, "yyyy-MM-dd") : "")}
        />
      </PopoverContent>
    </Popover>
  );
}

type CustomerFormViewProps = {
  isUpdate: boolean;
  isSaving: boolean;
  initialErrorMessage?: string | null;
  form: UseFormReturn<CustomerSharedFormValues>;
  createForm?: UseFormReturn<CustomerCreateFormValues>;
  onSubmit: (e?: React.BaseSyntheticEvent) => Promise<void>;
  listHref?: string;
  showMembership?: boolean;
};

function CustomerFormView({
  isUpdate,
  isSaving,
  initialErrorMessage = null,
  form,
  createForm,
  onSubmit,
  listHref = CUSTOMER_LIST_HREF,
  showMembership = true,
}: CustomerFormViewProps) {
  const [profileFileName, setProfileFileName] = React.useState<string | null>(null);
  const profileInputRef = React.useRef<HTMLInputElement>(null);

  const status = form.watch("status");
  const showClosureDate = status === "closed";
  const errors = form.formState.errors;
  const createErrors = createForm?.formState.errors as FieldErrors<CustomerCreateFormValues> | undefined;
  const displayName = `${form.watch("first_name")} ${form.watch("last_name")}`.trim();

  React.useEffect(() => {
    if (!showClosureDate) {
      form.setValue("closure_date", "");
    }
  }, [showClosureDate, form]);

  const handleProfileChange = (e: React.ChangeEvent<HTMLInputElement>) => {
    const file = e.target.files?.[0];
    if (!file) return;
    form.setValue("icon", file);
    setProfileFileName(file.name);
  };

  return (
    <form onSubmit={onSubmit} className="flex flex-col">
      <ErrorBanner message={initialErrorMessage} className="mb-4" />

      <FormPageHeader
        backHref={listHref}
        parentLabel="Customers"
        titleIcon={
          isUpdate ? (
            <Pencil className="size-4 text-primary" />
          ) : (
            <UserPlus className="size-4 text-primary" />
          )
        }
        title={isUpdate ? `Update ${displayName || "customer"}` : "Create new customer"}
      />

      <div className="space-y-6">
        <div className={cn("grid gap-4", isUpdate ? "lg:grid-cols-1" : "lg:grid-cols-2")}>
          <FormSection title="Account type">
            <FormField
              label="Account Type"
              htmlFor="account_type"
              required
              error={errors.account_type}
            >
              <Controller
                name="account_type"
                control={form.control}
                render={({ field }) => (
                  <FormSelect
                    id="account_type"
                    value={field.value}
                    onChange={field.onChange}
                    placeholder="Select account type"
                    options={ACCOUNT_TYPES}
                  />
                )}
              />
            </FormField>

            <FormField
              label="Tenant ID"
              htmlFor="subdomain"
              required
              error={errors.subdomain}
              description={
                isUpdate
                  ? "Tenant ID cannot be changed after the account is created."
                  : "This unique ID identifies the customer database. Creating a customer here does not provision DNS, a web subdomain, or filesystem resources."
              }
            >
              <InputGroup className="h-9">
                <InputGroupInput
                  id="subdomain"
                  placeholder="your-account-id"
                  value={form.watch("subdomain")}
                  onChange={(e) =>
                    form.setValue("subdomain", sanitizeSubdomain(e.target.value), {
                      shouldValidate: true,
                    })
                  }
                  readOnly={isUpdate}
                  aria-invalid={!!errors.subdomain}
                />
              </InputGroup>
            </FormField>
          </FormSection>

          {!isUpdate && createForm && showMembership ? (
            <FormSection title="Membership">
              <Controller
                name="create_order"
                control={createForm.control}
                render={({ field }) => (
                  <label
                    htmlFor="create_order"
                    className="flex cursor-pointer items-center gap-2.5 text-sm font-medium"
                  >
                    <Checkbox
                      id="create_order"
                      checked={field.value}
                      onCheckedChange={(checked) => field.onChange(checked === true)}
                    />
                    Create Order
                  </label>
                )}
              />

              <FormField label="Choose Plan" htmlFor="choose_plan" error={createErrors?.choose_plan}>
                <Controller
                  name="choose_plan"
                  control={createForm.control}
                  render={({ field }) => (
                    <FormSelect
                      id="choose_plan"
                      value={field.value ?? ""}
                      onChange={field.onChange}
                      placeholder="Please Select"
                      options={PRICE_PLANS}
                    />
                  )}
                />
              </FormField>
            </FormSection>
          ) : null}
        </div>

        <FormSection title="Registration Details">
          <div className="grid gap-4 md:grid-cols-2 xl:grid-cols-3">
            <FormField label="First Name" htmlFor="first_name" required error={errors.first_name}>
              <Input id="first_name" className="h-9" {...form.register("first_name")} />
            </FormField>
            <FormField label="Last Name" htmlFor="last_name" error={errors.last_name}>
              <Input id="last_name" className="h-9" {...form.register("last_name")} />
            </FormField>
            <FormField label="Mobile Number" htmlFor="phone" required error={errors.phone}>
              <Controller
                name="phone_country"
                control={form.control}
                render={({ field: countryField }) => (
                  <Controller
                    name="phone"
                    control={form.control}
                    render={({ field: phoneField }) => (
                      <PhoneInput
                        countryCode={countryField.value}
                        phone={phoneField.value}
                        onCountryChange={countryField.onChange}
                        onPhoneChange={phoneField.onChange}
                        invalid={!!errors.phone}
                      />
                    )}
                  />
                )}
              />
            </FormField>
          </div>

          <div className="grid gap-4 md:grid-cols-2 xl:grid-cols-4">
            <FormField label="E-mail address" htmlFor="email" required error={errors.email}>
              <Input
                id="email"
                type="email"
                className="h-9"
                autoComplete="email"
                {...form.register("email")}
              />
            </FormField>
            <FormField
              label="Confirm Email"
              htmlFor="confirm_email"
              required
              error={errors.confirm_email}
            >
              <Input
                id="confirm_email"
                className="h-9"
                autoComplete="email"
                {...form.register("confirm_email")}
              />
            </FormField>
            <FormField
              label={isUpdate ? "New Password" : "Enter Password"}
              htmlFor="password"
              required={!isUpdate}
              error={errors.password}
              description={isUpdate ? "Leave blank to keep the current password." : undefined}
            >
              <Input
                id="password"
                type="password"
                className="h-9"
                autoComplete="new-password"
                {...form.register("password")}
              />
            </FormField>
            <FormField
              label={isUpdate ? "Confirm New Password" : "Confirm Password"}
              htmlFor="con_password"
              required={!isUpdate}
              error={errors.con_password}
            >
              <Input
                id="con_password"
                type="password"
                className="h-9"
                autoComplete="new-password"
                {...form.register("con_password")}
              />
            </FormField>
          </div>

          <div className="grid gap-4 md:grid-cols-2 xl:grid-cols-3">
            <FormField label="Timezone" htmlFor="timezone" error={errors.timezone}>
              <Controller
                name="timezone"
                control={form.control}
                render={({ field }) => (
                  <FormSelect
                    id="timezone"
                    value={field.value ?? ""}
                    onChange={field.onChange}
                    placeholder="Please Select"
                    options={TIMEZONES}
                  />
                )}
              />
            </FormField>
            <FormField label="Company/Business Name" htmlFor="company_name">
              <Input id="company_name" className="h-9" {...form.register("company_name")} />
            </FormField>
            <FormField label="Registration Number" htmlFor="registration_number">
              <Input
                id="registration_number"
                className="h-9"
                {...form.register("registration_number")}
              />
            </FormField>
          </div>

          <div className="grid gap-4 md:grid-cols-2 xl:grid-cols-3">
            <FormField label="Business Address Line 1" htmlFor="company_address">
              <Input id="company_address" className="h-9" {...form.register("company_address")} />
            </FormField>
            <FormField label="City" htmlFor="city">
              <Input id="city" className="h-9" {...form.register("city")} />
            </FormField>
            <FormField label="Country" htmlFor="s_country_id">
              <Controller
                name="s_country_id"
                control={form.control}
                render={({ field }) => (
                  <FormSelect
                    id="s_country_id"
                    value={field.value ?? ""}
                    onChange={field.onChange}
                    placeholder="Please Select"
                    options={COUNTRIES}
                  />
                )}
              />
            </FormField>
          </div>

          <div
            className={cn(
              "grid gap-4",
              showClosureDate ? "md:grid-cols-2 xl:grid-cols-3" : "md:grid-cols-2",
            )}
          >
            <FormField label="Status" htmlFor="status" error={errors.status}>
              <Controller
                name="status"
                control={form.control}
                render={({ field }) => (
                  <FormSelect
                    id="status"
                    value={field.value}
                    onChange={field.onChange}
                    placeholder="Select status"
                    options={CUSTOMER_STATUSES}
                  />
                )}
              />
            </FormField>
            {showClosureDate ? (
              <FormField label="Closure date" htmlFor="closure_date" error={errors.closure_date}>
                <Controller
                  name="closure_date"
                  control={form.control}
                  render={({ field }) => (
                    <DatePickerField
                      value={field.value ?? ""}
                      onChange={field.onChange}
                      placeholder="Select closure date"
                    />
                  )}
                />
              </FormField>
            ) : null}
            <FormField label="Email Verified" htmlFor="email_verified">
              <Controller
                name="email_verified"
                control={form.control}
                render={({ field }) => (
                  <FormSelect
                    id="email_verified"
                    value={field.value}
                    onChange={field.onChange}
                    placeholder="Select"
                    options={EMAIL_VERIFIED_OPTIONS}
                  />
                )}
              />
            </FormField>
          </div>

          <FormField label="Profile Image" htmlFor="profile_image">
            <input
              ref={profileInputRef}
              id="profile_image"
              type="file"
              accept=".png,.jpg,.jpeg"
              className="sr-only"
              onChange={handleProfileChange}
            />
            <div className="flex items-center gap-3">
              <Button
                type="button"
                variant="outline"
                size="sm"
                className="h-9"
                onClick={() => profileInputRef.current?.click()}
              >
                Browse
              </Button>
              {profileFileName ? (
                <span className="truncate text-sm text-muted-foreground">{profileFileName}</span>
              ) : null}
            </div>
          </FormField>
        </FormSection>

        <Separator />
      </div>

      <FormSaveBar
        cancelHref={listHref}
        isSaving={isSaving}
        saveLabel={isUpdate ? "Save changes" : "Save customer"}
      />
    </form>
  );
}

export function CustomerCreateForm({
  mode = "create",
  customerId,
  initial,
  initialErrorMessage = null,
  createSubmitOptions,
  listHref = CUSTOMER_LIST_HREF,
  showMembership = true,
}: CustomerFormProps) {
  if (mode === "update") {
    if (!customerId) {
      throw new Error("customerId is required when mode is update");
    }

    return <CustomerUpdateForm customerId={customerId} initial={initial} initialErrorMessage={initialErrorMessage} />;
  }

  return (
    <CustomerCreateFormOnly
      initialErrorMessage={initialErrorMessage}
      createSubmitOptions={createSubmitOptions}
      listHref={listHref}
      showMembership={showMembership}
    />
  );
}

function CustomerCreateFormOnly({
  initialErrorMessage = null,
  createSubmitOptions,
  listHref,
  showMembership,
}: {
  initialErrorMessage?: string | null;
  createSubmitOptions?: CustomerCreateSubmitOptions;
  listHref: string;
  showMembership: boolean;
}) {
  const { form, sharedForm, isSaving, onSubmit } = useCustomerCreateForm(createSubmitOptions);

  return (
    <CustomerFormView
      isUpdate={false}
      isSaving={isSaving}
      initialErrorMessage={initialErrorMessage}
      form={sharedForm}
      createForm={form}
      onSubmit={onSubmit}
      listHref={listHref}
      showMembership={showMembership}
    />
  );
}

function CustomerUpdateForm({
  customerId,
  initial,
  initialErrorMessage = null,
}: {
  customerId: number;
  initial?: CustomerUpdateFormValues;
  initialErrorMessage?: string | null;
}) {
  const { sharedForm, isSaving, onSubmit } = useCustomerUpdateForm(customerId, initial);

  return (
    <CustomerFormView
      isUpdate
      isSaving={isSaving}
      initialErrorMessage={initialErrorMessage}
      form={sharedForm}
      onSubmit={onSubmit}
    />
  );
}
