import { Checkbox, Grid, Input, NumberInput, Select, TextInput } from '@mantine/core';
import type { SaveSeafarerRegistration } from '@ema-platform/api';
import { AmharicDatePicker, CountrySelect, getCountryCode, getCountryName } from '@ema-platform/ui';
import { LocationPicker } from '../../location/components/LocationPicker';

export type AnswerKey = keyof SaveSeafarerRegistration;

/** What every step receives: the answers, a setter, the errors, and whether it is locked. */
export interface StepProps {
  form: SaveSeafarerRegistration;
  set: (key: AnswerKey, value: unknown) => void;
  errors: Partial<Record<AnswerKey, string>>;
  disabled?: boolean;
}

interface FieldProps extends StepProps {
  name: AnswerKey;
  label: string;
  required?: boolean;
  description?: string;
  maxLength?: number;
  span?: number;
}

const common = (p: FieldProps) => ({
  label: p.label,
  description: p.description,
  withAsterisk: p.required,
  error: p.errors[p.name],
  disabled: p.disabled,
});

const Col = ({ span = 6, children }: { span?: number; children: React.ReactNode }) => (
  <Grid.Col span={{ base: 12, md: span }}>{children}</Grid.Col>
);

export function TextField(p: FieldProps) {
  return (
    <Col span={p.span}>
      <TextInput
        {...common(p)}
        maxLength={p.maxLength}
        value={(p.form[p.name] as string) ?? ''}
        onChange={(e) => p.set(p.name, e.currentTarget.value)}
      />
    </Col>
  );
}

export function SelectField(p: FieldProps & { options: { value: string; label: string }[] }) {
  return (
    <Col span={p.span}>
      <Select
        {...common(p)}
        data={p.options}
        value={(p.form[p.name] as string) ?? null}
        onChange={(v) => p.set(p.name, v)}
        clearable={!p.required}
      />
    </Col>
  );
}

export function DateField(p: FieldProps & { minDate?: Date | string; maxDate?: Date | string }) {
  return (
    <Col span={p.span}>
      <AmharicDatePicker
        label={p.label}
        error={p.errors[p.name]}
        disabled={p.disabled}
        required={p.required}
        dateFormat="date"
        minDate={p.minDate}
        maxDate={p.maxDate}
        value={(p.form[p.name] as string) ?? ''}
        onChange={(v) => p.set(p.name, v)}
      />
    </Col>
  );
}

export function NumberField(p: FieldProps) {
  return (
    <Col span={p.span}>
      <NumberInput
        {...common(p)}
        // Not clamped: validation reports an out-of-range figure instead of
        // Mantine quietly rewriting what the applicant typed.
        value={(p.form[p.name] as number) ?? ''}
        onChange={(v) => p.set(p.name, v === '' ? null : Number(v))}
      />
    </Col>
  );
}

/** Stored as the full country name, like the profile; picked by alpha-2 code. */
export function NationalityField(p: FieldProps) {
  const stored = (p.form[p.name] as string) ?? '';
  return (
    <Col span={p.span}>
      <CountrySelect
        {...common(p)}
        required={p.required}
        demonym
        value={getCountryCode(stored) ?? (stored || null)}
        onChange={(code) => p.set(p.name, code ? getCountryName(code) || code : null)}
      />
    </Col>
  );
}

export function LocationField(p: FieldProps) {
  return (
    <Col span={p.span}>
      <Input.Wrapper
        label={p.label}
        description={p.description}
        withAsterisk={p.required}
        error={p.errors[p.name]}
      >
        <LocationPicker
          value={(p.form[p.name] as string) ?? undefined}
          onChange={(id) => p.set(p.name, id)}
          required={p.required}
          maxDepth={3}
          disabled={p.disabled}
        />
      </Input.Wrapper>
    </Col>
  );
}

export function CheckboxField(p: FieldProps) {
  return (
    <Col span={12}>
      <Checkbox
        label={p.label}
        error={p.errors[p.name]}
        disabled={p.disabled}
        checked={Boolean(p.form[p.name])}
        onChange={(e) => p.set(p.name, e.currentTarget.checked)}
      />
    </Col>
  );
}
