"use client";

import * as React from "react";
import Link from "next/link";

import { zodResolver } from "@hookform/resolvers/zod";
import { ArrowLeft, Save, Upload, UserPlus } from "lucide-react";
import { Controller, useForm } from "react-hook-form";
import { z } from "zod";

import { useDashboardFormSubmit } from "@/app/dashboard/_components/use-dashboard-form-submit";
import {
  PHONE_COUNTRIES,
  TIMEZONES,
} from "@/app/dashboard/customers/_components/customer-form/constants";
import { FormField } from "@/components/form/form-field";
import { ErrorBanner } from "@/components/shared/error-banner";
import { Button } from "@/components/ui/button";
import { Checkbox } from "@/components/ui/checkbox";
import {
  InputGroup,
  InputGroupAddon,
  InputGroupInput,
  InputGroupText,
} from "@/components/ui/input-group";
import { Input } from "@/components/ui/input";
import {
  Select,
  SelectContent,
  SelectItem,
  SelectTrigger,
  SelectValue,
} from "@/components/ui/select";
import { CUSTOMER_MIN_PASSWORD_LENGTH } from "@/config/password-policy";
import { getCustomerEmailDomainSuffix } from "@/config/customer-email-domain";

import { StaffMultiSelect } from "./staff-multi-select";

type StaffOption = {
  id: number;
  name: string;
  email: string;
  groupId: number | null;
  groupName: string | null;
};

type GroupOption = {
  group_id: number;
  name: string;
};

type TenantCustomerCreateFormProps = {
  tenant: string;
  staff: StaffOption[];
  groups: GroupOption[];
  initialErrorMessage?: string | null;
};

const accountIdPattern = /^[a-z0-9]([a-z0-9-]*[a-z0-9])?$/;

const schema = z
  .object({
    assigned_to: z.array(z.string()),
    primary_rm: z.array(z.string()),
    joined_date: z.string(),
    first_name: z.string().trim().min(1, "First name is required"),
    last_name: z.string(),
    phone_country: z.string(),
    phone: z.string().trim().min(1, "Mobile number is required"),
    subdomain: z
      .string()
      .trim()
      .min(1, "Account ID is required")
      .regex(accountIdPattern, "Use lowercase letters, numbers, and hyphens only"),
    email: z.string().trim().email("Enter a valid email address"),
    confirm_email: z.string().trim().email("Confirm the email address"),
    password: z
      .string()
      .min(
        CUSTOMER_MIN_PASSWORD_LENGTH,
        `Password must be at least ${CUSTOMER_MIN_PASSWORD_LENGTH} characters`,
      ),
    con_password: z.string().min(1, "Confirm the password"),
    timezone: z.string().min(1, "Timezone is required"),
    company_name: z.string(),
    registration_number: z.string(),
    company_address: z.string(),
    send_credential: z.boolean(),
  })
  .refine((values) => values.email === values.confirm_email, {
    path: ["confirm_email"],
    message: "Email confirmation does not match",
  })
  .refine((values) => values.password === values.con_password, {
    path: ["con_password"],
    message: "Password confirmation does not match",
  });

type FormValues = z.infer<typeof schema>;

const defaults: FormValues = {
  assigned_to: [],
  primary_rm: [],
  joined_date: "",
  first_name: "",
  last_name: "",
  phone_country: "AE",
  phone: "",
  subdomain: "",
  email: "",
  confirm_email: "",
  password: "",
  con_password: "",
  timezone: "UTC",
  company_name: "",
  registration_number: "",
  company_address: "",
  send_credential: false,
};

function sanitizeAccountId(value: string) {
  return value
    .toLowerCase()
    .replace(/[^a-z0-9-]/g, "")
    .replace(/^-+/, "")
    .replace(/-+$/, "");
}

function sanitizePhone(value: string) {
  return value.replace(/\D/g, "");
}

export function TenantCustomerCreateForm({
  tenant,
  staff,
  groups,
  initialErrorMessage = null,
}: TenantCustomerCreateFormProps) {
  const listHref = `/customer/${tenant}/admin/customers`;
  const [groupFilter, setGroupFilter] = React.useState("__all__");
  const [profileName, setProfileName] = React.useState("");
  const profileInput = React.useRef<HTMLInputElement>(null);
  const form = useForm<FormValues>({
    resolver: zodResolver(schema),
    defaultValues: defaults,
  });

  const { isSaving, submit } = useDashboardFormSubmit<FormValues>({
    mode: "create",
    createUrl: `${listHref}/create/submit`,
    updateUrl: "",
    listHref,
    timeoutMs: 120_000,
    saveFailMessage: "Customer could not be created.",
    messages: {
      createFail: "Customer could not be created.",
      updateFail: "Customer could not be updated.",
      createSuccess: "Customer and database created.",
      updateSuccess: "Customer updated.",
    },
  });

  const staffOptions = React.useMemo(
    () =>
      staff.map((member) => ({
        value: String(member.id),
        label: member.name || member.email,
      })),
    [staff],
  );
  const errors = form.formState.errors;

  function handleGroupFilterChange(value: string) {
    setGroupFilter(value);
    if (value === "__all__") {
      return;
    }
    // Match Yii2: selecting a group selects all staff in that group.
    const ids = staff
      .filter((member) => member.groupId === Number(value))
      .map((member) => String(member.id));
    form.setValue("assigned_to", ids, { shouldDirty: true, shouldValidate: true });
  }

  return (
    <form onSubmit={form.handleSubmit(submit)} className="flex min-h-full flex-col">
      <ErrorBanner message={initialErrorMessage} className="mb-4" />

      <header className="mb-5 flex flex-wrap items-center justify-between gap-3 border-b pb-4">
        <div>
          <div className="flex items-center gap-2">
            <UserPlus className="size-5 text-primary" />
            <h1 className="text-xl font-semibold tracking-tight">Create New Customer</h1>
          </div>
          <p className="mt-1 text-sm text-muted-foreground">
            Create a customer under this account and provision its database.
          </p>
        </div>
        <Button asChild type="button" variant="destructive" size="sm">
          <Link href={listHref}>
            <ArrowLeft />
            Cancel
          </Link>
        </Button>
      </header>

      <div className="space-y-5 pb-24">
        <section className="grid items-start gap-4 rounded-lg border bg-card p-4 md:grid-cols-2 xl:grid-cols-3">
          <div className="flex flex-col gap-1.5">
            <div className="flex h-8 items-center justify-between gap-2">
              <span className="text-sm font-medium leading-none">Assigned To</span>
              <Select value={groupFilter} onValueChange={handleGroupFilterChange}>
                <SelectTrigger className="h-7 w-[8.5rem] shrink-0 text-xs">
                  <SelectValue placeholder="Select Group" />
                </SelectTrigger>
                <SelectContent>
                  <SelectItem value="__all__">All groups</SelectItem>
                  {groups.map((group) => (
                    <SelectItem key={group.group_id} value={String(group.group_id)}>
                      {group.name}
                    </SelectItem>
                  ))}
                </SelectContent>
              </Select>
            </div>
            <Controller
              name="assigned_to"
              control={form.control}
              render={({ field }) => (
                <StaffMultiSelect
                  id="assigned_to"
                  value={field.value}
                  onChange={field.onChange}
                  options={staffOptions}
                  placeholder="Select staff"
                />
              )}
            />
          </div>

          <div className="flex flex-col gap-1.5">
            <div className="flex h-8 items-center">
              <label htmlFor="primary_rm" className="text-sm font-medium leading-none">
                Primary RM
              </label>
            </div>
            <Controller
              name="primary_rm"
              control={form.control}
              render={({ field }) => (
                <StaffMultiSelect
                  id="primary_rm"
                  value={field.value}
                  onChange={field.onChange}
                  options={staffOptions}
                  placeholder="Select primary RM"
                />
              )}
            />
          </div>

          <div className="flex flex-col gap-1.5">
            <div className="flex h-8 items-center">
              <label htmlFor="joined_date" className="text-sm font-medium leading-none">
                Customer Since Date
              </label>
            </div>
            <Input
              id="joined_date"
              type="date"
              className="h-9"
              {...form.register("joined_date")}
            />
          </div>
        </section>

        <section className="grid gap-4 rounded-lg border bg-card p-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" placeholder="First Name" {...form.register("first_name")} />
          </FormField>
          <FormField label="Last Name" htmlFor="last_name">
            <Input id="last_name" placeholder="Last Name" {...form.register("last_name")} />
          </FormField>
          <FormField label="Profile Image" htmlFor="profile_image">
            <input
              ref={profileInput}
              id="profile_image"
              type="file"
              accept=".png,.jpg,.jpeg"
              className="sr-only"
              onChange={(event) => setProfileName(event.target.files?.[0]?.name ?? "")}
            />
            <Button
              type="button"
              variant="outline"
              className="w-full justify-start"
              onClick={() => profileInput.current?.click()}
            >
              <Upload />
              {profileName || "Browse"}
            </Button>
          </FormField>

          <FormField label="Mobile Number" htmlFor="phone" required error={errors.phone}>
            <Controller
              name="phone"
              control={form.control}
              render={({ field: phoneField }) => (
                <InputGroup>
                  <InputGroupAddon align="inline-start" className="border-r">
                    <Controller
                      name="phone_country"
                      control={form.control}
                      render={({ field }) => (
                        <Select value={field.value} onValueChange={field.onChange}>
                          <SelectTrigger className="h-7 w-28 border-0 bg-transparent shadow-none">
                            <SelectValue />
                          </SelectTrigger>
                          <SelectContent>
                            {PHONE_COUNTRIES.map((country) => (
                              <SelectItem key={country.code} value={country.code}>
                                {country.flag} {country.dial}
                              </SelectItem>
                            ))}
                          </SelectContent>
                        </Select>
                      )}
                    />
                  </InputGroupAddon>
                  <InputGroupInput
                    id="phone"
                    placeholder="e.g. 6 701 5757"
                    value={phoneField.value}
                    onChange={(event) => phoneField.onChange(sanitizePhone(event.target.value))}
                  />
                </InputGroup>
              )}
            />
          </FormField>

          <FormField
            label="Account ID"
            htmlFor="subdomain"
            required
            error={errors.subdomain}
            description="Unique database identifier. No DNS or web subdomain is created."
            className="xl:col-span-2"
          >
            <Controller
              name="subdomain"
              control={form.control}
              render={({ field }) => (
                <InputGroup>
                  <InputGroupInput
                    id="subdomain"
                    placeholder="account-id"
                    value={field.value}
                    onChange={(event) => field.onChange(sanitizeAccountId(event.target.value))}
                  />
                  <InputGroupAddon align="inline-end">
                    <InputGroupText>{getCustomerEmailDomainSuffix()}</InputGroupText>
                  </InputGroupAddon>
                </InputGroup>
              )}
            />
          </FormField>

          <FormField label="E-Mail Address" htmlFor="email" required error={errors.email}>
            <Input
              id="email"
              type="email"
              placeholder="E-mail Address"
              autoComplete="email"
              {...form.register("email")}
            />
          </FormField>
          <FormField
            label="Confirm Email"
            htmlFor="confirm_email"
            required
            error={errors.confirm_email}
            className="xl:col-span-2"
          >
            <Input
              id="confirm_email"
              type="email"
              placeholder="Confirm Email"
              autoComplete="email"
              {...form.register("confirm_email")}
            />
          </FormField>

          <FormField label="Enter Password" htmlFor="password" required error={errors.password}>
            <Input
              id="password"
              type="password"
              placeholder="Enter Password"
              autoComplete="new-password"
              {...form.register("password")}
            />
          </FormField>
          <FormField
            label="Confirm Password"
            htmlFor="con_password"
            required
            error={errors.con_password}
          >
            <Input
              id="con_password"
              type="password"
              placeholder="Confirm Password"
              autoComplete="new-password"
              {...form.register("con_password")}
            />
          </FormField>
          <FormField label="Timezone" htmlFor="timezone" required error={errors.timezone}>
            <Controller
              name="timezone"
              control={form.control}
              render={({ field }) => (
                <Select value={field.value} onValueChange={field.onChange}>
                  <SelectTrigger id="timezone">
                    <SelectValue placeholder="Select timezone" />
                  </SelectTrigger>
                  <SelectContent>
                    {TIMEZONES.map((timezone) => (
                      <SelectItem key={timezone.value} value={timezone.value}>
                        {timezone.label}
                      </SelectItem>
                    ))}
                  </SelectContent>
                </Select>
              )}
            />
          </FormField>

          <FormField label="Company/Business Name" htmlFor="company_name">
            <Input
              id="company_name"
              placeholder="Company/Business Name"
              {...form.register("company_name")}
            />
          </FormField>
          <FormField label="Registration Number" htmlFor="registration_number" className="xl:col-span-2">
            <Input
              id="registration_number"
              placeholder="Registration Number"
              {...form.register("registration_number")}
            />
          </FormField>
          <FormField
            label="Business Address Line"
            htmlFor="company_address"
            className="md:col-span-2 xl:col-span-3"
          >
            <Input
              id="company_address"
              placeholder="Business Address Line 1"
              {...form.register("company_address")}
            />
          </FormField>
        </section>
      </div>

      <footer className="sticky bottom-0 z-20 mt-auto flex flex-wrap items-center justify-between gap-3 border-t bg-background/95 px-4 py-3 shadow-[0_-4px_20px_-10px_rgba(0,0,0,0.3)] backdrop-blur">
        <Controller
          name="send_credential"
          control={form.control}
          render={({ field }) => (
            <label className="flex cursor-pointer items-center gap-2 text-sm font-medium">
              <Checkbox
                checked={field.value}
                onCheckedChange={(checked) => field.onChange(checked === true)}
              />
              Send Credential
            </label>
          )}
        />
        <Button type="submit" disabled={isSaving}>
          <Save />
          {isSaving ? "Creating…" : "Save changes"}
        </Button>
      </footer>
    </form>
  );
}
