'use client';

import * as FieldIcons from './Icons';

import { useState } from 'react';
import { AlertIcon, CheckCircleIcon, LockIcon, SendIcon, Spinner } from './Icons';

type Props = {
  countrySlug?: string;
  citySlug?: string;
  practiceAreaSlug?: string;
  lawyerSlug?: string;
  heading: string;
  intro: string;
  sourcePath: string;
  consentText: string;
};

const EMAIL = /^[^\s@]+@[^\s@]+\.[^\s@]{2,}$/;
const MIN_DESC = 20;
const MAX_DESC = 3000;

/** Same rules as the API, checked before sending so mistakes show next to the field straight away */
function validate(fd: FormData): Record<string, string> {
  const e: Record<string, string> = {};
  const name = String(fd.get('name') ?? '').trim();
  const email = String(fd.get('email') ?? '').trim();
  const desc = String(fd.get('description') ?? '').trim();
  if (name.length < 2) e.name = 'Enter your name.';
  if (!EMAIL.test(email)) e.email = 'Enter a valid email address, like name@example.com.';
  if (desc.length < MIN_DESC) e.description = `Describe your situation in at least ${MIN_DESC} characters.`;
  if (fd.get('consent') !== 'on') e.consent = 'Tick the box to agree before sending.';
  return e;
}

export function LeadForm(p: Props) {
  const [state, setState] = useState<'idle' | 'sending' | 'done' | 'error'>('idle');
  const [message, setMessage] = useState('');
  const [errors, setErrors] = useState<Record<string, string>>({});
  const [descLen, setDescLen] = useState(0);

  async function onSubmit(e: React.FormEvent<HTMLFormElement>) {
    e.preventDefault();
    const formEl = e.currentTarget;
    const fd = new FormData(formEl);
    const local = validate(fd);
    if (Object.keys(local).length) {
      setErrors(local);
      setState('error');
      setMessage('Check the highlighted fields.');
      formEl.querySelector<HTMLElement>(`[name="${Object.keys(local)[0]}"]`)?.focus();
      return;
    }
    setState('sending');
    setErrors({});
    try {
      const res = await fetch('/api/v1/leads/', {
        method: 'POST',
        headers: { 'content-type': 'application/json' },
        body: JSON.stringify({
          name: String(fd.get('name')).trim(),
          email: String(fd.get('email')).trim(),
          phone: String(fd.get('phone') ?? '').trim() || undefined,
          description: String(fd.get('description')).trim(),
          consent: true,
          website: fd.get('website') || undefined,
          countrySlug: p.countrySlug,
          citySlug: p.citySlug,
          practiceAreaSlug: p.practiceAreaSlug,
          lawyerSlug: p.lawyerSlug,
          sourcePath: p.sourcePath,
        }),
      });
      const data = await res.json().catch(() => ({}));
      if (res.status === 429) {
        setState('error');
        setMessage('Too many enquiries from this connection. Try again in an hour.');
      } else if (!res.ok) {
        setState('error');
        setErrors(Object.fromEntries((data.issues ?? []).map((i: { path: string; message: string }) => [i.path, i.message])));
        setMessage(data.issues ? 'Check the highlighted fields.' : 'Your enquiry was not sent. Try again in a moment.');
      } else {
        setState('done');
        setMessage(data.message ?? 'Enquiry sent.');
      }
    } catch {
      setState('error');
      setMessage('Your enquiry was not sent because the connection failed. Check your connection and try again.');
    }
  }

  if (state === 'done')
    return (
      <div role="status" className="card fade-up border-ledger/30 bg-ledger-tint p-6 text-center">
        <span className="mx-auto grid h-12 w-12 place-items-center rounded-full bg-ledger text-ledger-ink">
          <CheckCircleIcon className="h-6 w-6" />
        </span>
        <p className="mt-3 font-serif text-xl font-semibold text-ink">Enquiry sent</p>
        <p className="mt-1 text-sm leading-relaxed text-ink-2">{message}</p>
        <button
          type="button"
          className="btn btn-quiet btn-sm mt-4"
          onClick={() => {
            setState('idle');
            setDescLen(0);
          }}
        >
          Send another enquiry
        </button>
      </div>
    );

  const field = (k: string) => ({ 'aria-invalid': !!errors[k] || undefined, 'aria-describedby': errors[k] ? `lead-${k}-err` : undefined });
  const err = (k: string) =>
    errors[k] && (
      <span id={`lead-${k}-err`} className="mt-1.5 flex items-start gap-1 text-xs font-medium text-danger">
        <AlertIcon className="mt-px h-3.5 w-3.5" />
        {errors[k]}
      </span>
    );
  const clear = (k: string) => errors[k] && setErrors(({ [k]: _drop, ...rest }) => rest);

  return (
    <form onSubmit={onSubmit} noValidate className="card space-y-4 p-5 shadow-md sm:p-6">
      <div>
        <span className="mb-3 grid h-10 w-10 place-items-center rounded-xl bg-ledger-soft text-ledger">
          <SendIcon className="h-5 w-5" />
        </span>
        <h2 className="font-serif text-xl font-semibold leading-snug">{p.heading}</h2>
        <p className="mt-1 text-sm leading-relaxed text-muted">{p.intro}</p>
      </div>
      <label className="block">
        <span className="field-label"><FieldIcons.UserIcon />Your name</span>
        <input name="name" required autoComplete="name" maxLength={150} className="field" onInput={() => clear('name')} {...field('name')} />
        {err('name')}
      </label>
      <label className="block">
        <span className="field-label"><FieldIcons.MailIcon />Email</span>
        <input name="email" type="email" required autoComplete="email" inputMode="email" maxLength={255} className="field" onInput={() => clear('email')} {...field('email')} />
        {err('email')}
      </label>
      <label className="block">
        <span className="field-label">
          Phone <span className="font-normal text-muted">(optional)</span>
        </span>
        <input name="phone" type="tel" autoComplete="tel" inputMode="tel" maxLength={60} className="field" />
      </label>
      <label className="block">
        <span className="field-label"><FieldIcons.FileTextIcon />What do you need help with?</span>
        <textarea
          name="description"
          required
          rows={4}
          maxLength={MAX_DESC}
          className="field"
          placeholder="A short summary — avoid sharing confidential details here."
          onInput={(e) => {
            setDescLen(e.currentTarget.value.trim().length);
            clear('description');
          }}
          {...field('description')}
        />
        <span className="mt-1 flex justify-between gap-2 text-xs text-muted">
          <span>{descLen < MIN_DESC ? `${MIN_DESC - descLen} more characters needed` : 'Looks good'}</span>
          <span className="num">
            {descLen}/{MAX_DESC}
          </span>
        </span>
        {err('description')}
      </label>
      <input name="website" tabIndex={-1} autoComplete="off" className="hidden" aria-hidden />
      <label className="flex items-start gap-2.5 rounded-lg bg-paper p-3 text-xs leading-relaxed text-ink-2">
        <input name="consent" type="checkbox" required className="mt-0.5 shrink-0" onChange={() => clear('consent')} {...field('consent')} />
        <span>{p.consentText}</span>
      </label>
      {err('consent')}
      {state === 'error' && message && (
        <p role="alert" className="flex items-start gap-2 rounded-lg border border-danger/30 bg-danger-soft px-3 py-2.5 text-sm text-danger">
          <AlertIcon className="mt-0.5 h-4 w-4" />
          {message}
        </p>
      )}
      <button type="submit" disabled={state === 'sending'} className="btn btn-primary w-full">
        {state === 'sending' ? (
          <>
            <Spinner /> Sending…
          </>
        ) : (
          <>
            <SendIcon className="h-4 w-4" /> Send enquiry
          </>
        )}
      </button>
      <p className="flex items-center justify-center gap-1.5 text-xs text-muted">
        <LockIcon className="h-3.5 w-3.5" /> Shared only with the lawyers you are matched with
      </p>
    </form>
  );
}
