import React from 'react';
import { Col, Collapse, Form, Input, Row } from 'antd';
import InputPhone from '@/components/form/InputPhone';
import { userEmailValidator, userPhoneNoValidator, leadUserNameValidator } from '@/utills/validator';
import type { IBookingApplicant } from '../interface';

const { Panel } = Collapse;

type ApplicantKey = 'applicant1' | 'applicant2';
const FIELDS = ['client_name', 'client_mobile', 'client_email'] as const;
type ApplicantField = typeof FIELDS[number];

export interface ApplicantFormValues {
  client_name?: string
  client_mobile?: string | { number: string, country?: string }
  client_email?: string
}

// The phone widget yields { number, country }; stored/legacy values are plain strings.
// A bare country code (e.g. "+91") counts as "nothing entered".
export const phoneToString = (v: unknown): string => {
  const raw = typeof v === 'object' && v !== null ? (v as { number?: string }).number : (v as string | undefined);
  const str = String(raw ?? '').trim();
  return /^\+?\d{0,3}$/.test(str) && str.startsWith('+') ? '' : str;
};

const isBlank = (v: unknown) => !(typeof v === 'object' && v !== null ? phoneToString(v) : String(v ?? '').trim());

// Maps stored booking_applicant rows (is_optional 0 -> Applicant 1, 1 -> Applicant 2) to form values.
export const applicantsToFormValues = (
  applicants?: { applicant1: IBookingApplicant | null, applicant2: IBookingApplicant | null } | null
) => {
  const pick = (a?: IBookingApplicant | null): ApplicantFormValues | undefined =>
    a ? { client_name: a.client_name, client_mobile: a.client_mobile, client_email: a.client_email } : undefined;
  return { applicant1: pick(applicants?.applicant1), applicant2: pick(applicants?.applicant2) };
};

// Builds the `applicants` API payload. Applicant 2 is left out entirely when its section is empty.
export const buildApplicantsPayload = (values: { applicant1?: ApplicantFormValues, applicant2?: ApplicantFormValues }) => {
  const clean = (a?: ApplicantFormValues) => ({
    client_name: String(a?.client_name ?? '').trim(),
    client_mobile: phoneToString(a?.client_mobile),
    client_email: String(a?.client_email ?? '').trim(),
  });
  const payload = [{ ...clean(values.applicant1), is_optional: 0 }];
  const a2 = clean(values.applicant2);
  if (FIELDS.some((f) => a2[f])) {
    payload.push({ ...a2, is_optional: 1 });
  }
  return payload;
};

// Panels that contain a failed field, so the parent can expand them after a failed submit.
export const applicantPanelsWithErrors = (errorFields: { name: (string | number)[] }[] = []) =>
  (['applicant1', 'applicant2'] as ApplicantKey[]).filter((k) => errorFields.some((e) => e.name?.[0] === k));

interface Props {
  activeKey: string[]
  onChange: (keys: string[]) => void
}

const A2_LABELS: Record<ApplicantField, string> = {
  client_name: 'name',
  client_mobile: 'contact',
  client_email: 'email',
};

// Applicant 1 (mandatory) / Applicant 2 (optional) expanders for a booking form.
// Panels are force-rendered so collapsed fields still take part in validation.
const BookingApplicants: React.FC<Props> = ({ activeKey, onChange }) => {
  const form = Form.useFormInstance();

  // Applicant 2 is optional, but once any field is filled, name and contact are needed
  // (email stays optional for both applicants either way).
  const a2Required = (field: Exclude<ApplicantField, 'client_email'>) => ({
    validator: (_: unknown, value: unknown) => {
      const a2 = form.getFieldValue('applicant2') || {};
      const anyFilled = FIELDS.some((f) => !isBlank(a2[f]));
      if (anyFilled && isBlank(value)) {
        return Promise.reject(new Error(`Please enter Applicant 2 ${A2_LABELS[field]}`));
      }
      return Promise.resolve();
    },
  });

  // Re-run the whole Applicant 2 group as the user types so "all or nothing" errors clear together.
  const revalidateA2 = () => {
    const names = FIELDS.map((f) => ['applicant2', f]);
    if (names.some((n) => form.isFieldTouched(n))) {
      form.validateFields(names).catch(() => undefined);
    }
  };

  return (
    <Collapse activeKey={activeKey} onChange={(k) => onChange(Array.isArray(k) ? k : [k])} className="mb-4">
      <Panel header="Applicant 1 *" key="applicant1" forceRender>
        <Row gutter={16}>
        <Col span={24} md={12}>
          <Form.Item
            label="Client Name"
            name={['applicant1', 'client_name']}
            rules={[{ validator: leadUserNameValidator('Applicant 1 Client') }]}>
            <Input placeholder="Client name" maxLength={50} />
          </Form.Item>
        </Col>
        <Col span={24} md={12}>
          <InputPhone
            label="Client Contact"
            name={['applicant1', 'client_mobile'] as unknown as string}
            defaultCountry="in"
            enableSearch
            rules={[{ validator: userPhoneNoValidator('Applicant 1 client contact') }]}
          />
        </Col>
        <Col span={24} md={12}>
          <Form.Item
            label="Client Email ID"
            name={['applicant1', 'client_email']}
            rules={[{ validator: userEmailValidator('Applicant 1 client', false) }]}>
            <Input placeholder="Client email" maxLength={70} />
          </Form.Item>
        </Col>
        </Row>
      </Panel>
      <Panel header="Applicant 2" key="applicant2" forceRender>
        <Row gutter={16}>
        <Col span={24} md={12}>
          <Form.Item
            label="Client Name"
            name={['applicant2', 'client_name']}
            rules={[
              a2Required('client_name'),
              { validator: (_: unknown, v: string) => (isBlank(v) ? Promise.resolve() : leadUserNameValidator('Applicant 2 Client')(_, v)) },
            ]}>
            <Input placeholder="Client name" maxLength={50} onChange={revalidateA2} />
          </Form.Item>
        </Col>
        <Col span={24} md={12}>
          <InputPhone
            label="Client Contact"
            name={['applicant2', 'client_mobile'] as unknown as string}
            defaultCountry="in"
            enableSearch
            onChange={revalidateA2}
            rules={[
              a2Required('client_mobile'),
              { validator: (_: unknown, v: unknown) => (isBlank(v) ? Promise.resolve() : userPhoneNoValidator('Applicant 2 client contact', false)(_, v as string)) },
            ]}
          />
        </Col>
        <Col span={24} md={12}>
          <Form.Item
            label="Client Email ID"
            name={['applicant2', 'client_email']}
            rules={[{ validator: (_: unknown, v: string) => userEmailValidator('Applicant 2 client', false)(_, v) }]}>
            <Input placeholder="Client email" maxLength={70} onChange={revalidateA2} />
          </Form.Item>
        </Col>
        </Row>
      </Panel>
    </Collapse>
  );
};

export default BookingApplicants;
