'use client';
import { FunctionComponent, useState } from 'react';
import { useTranslations } from 'next-intl';
import FormControlLabel from '@mui/material/FormControlLabel';
import Stack from '@mui/material/Stack';
import Switch from '@mui/material/Switch';
import TextField from '@mui/material/TextField';
import { AppButton } from '@/components/common';
import { cityCentroid } from '@/services/geography/constants';
import type { CreateAddressInput, LatLng } from '@/services/addresses/types';
import CascadingRegionSelect, { type CascadingRegionValue } from './CascadingRegionSelect';
import AddressMapPicker from './AddressMapPicker';

/** Prefill for edit (or empty for add). `provinceId` is needed to prefill the cascade. */
export interface AddressFormInitial {
  title?: string;
  provinceId?: number | null;
  cityId?: number | null;
  districtId?: number | null;
  addressLine?: string | null;
  latitude?: number | null;
  longitude?: number | null;
  isPrimary?: boolean;
}

export interface AddressFormProps {
  initial?: AddressFormInitial;
  submitting?: boolean;
  onSubmit: (input: CreateAddressInput) => void;
  onCancel?: () => void;
}

// Only prefill the region when we have the province — a city id without its province can't drive
// the (per-province) city query, so the cascade starts fresh instead of showing a dead value.
function initialRegion(initial?: AddressFormInitial): CascadingRegionValue {
  if (initial?.provinceId == null) return { provinceId: null, cityId: null, districtId: null };
  return { provinceId: initial.provinceId, cityId: initial.cityId ?? null, districtId: initial.districtId ?? null };
}

function initialPin(initial?: AddressFormInitial): LatLng | null {
  return initial?.latitude != null && initial?.longitude != null
    ? { latitude: initial.latitude, longitude: initial.longitude }
    : null;
}

/**
 * The add/edit address form body — the cascading region dropdowns + the map-pin picker + a
 * title and street address + a "set as primary" toggle. Validation: **city required**, **pin
 * required** (surfaced inline), title + street required, **district optional**. Emits a
 * `CreateAddressInput` carrying the picked coordinates. Reused for create and edit.
 * @component AddressForm
 */
const AddressForm: FunctionComponent<AddressFormProps> = ({ initial, submitting = false, onSubmit, onCancel }) => {
  const t = useTranslations('address');
  const tc = useTranslations('common');

  const [title, setTitle] = useState(initial?.title ?? '');
  const [region, setRegion] = useState<CascadingRegionValue>(() => initialRegion(initial));
  const [addressLine, setAddressLine] = useState(initial?.addressLine ?? '');
  const [pin, setPin] = useState<LatLng | null>(() => initialPin(initial));
  const [isPrimary, setIsPrimary] = useState(initial?.isPrimary ?? false);

  const [titleError, setTitleError] = useState(false);
  const [cityError, setCityError] = useState(false);
  const [lineError, setLineError] = useState(false);
  const [pinError, setPinError] = useState(false);

  const handleSubmit = () => {
    const titleInvalid = title.trim().length === 0;
    const cityInvalid = region.cityId == null;
    const lineInvalid = addressLine.trim().length === 0;
    const pinInvalid = pin == null;

    setTitleError(titleInvalid);
    setCityError(cityInvalid);
    setLineError(lineInvalid);
    setPinError(pinInvalid);
    if (titleInvalid || cityInvalid || lineInvalid || pinInvalid) return;

    onSubmit({
      title: title.trim(),
      provinceId: region.provinceId as number,
      cityId: region.cityId as number,
      districtId: region.districtId,
      addressLine: addressLine.trim(),
      latitude: pin!.latitude,
      longitude: pin!.longitude,
      isPrimary,
    });
  };

  return (
    <Stack sx={{ gap: 2.5 }}>
      <TextField
        label={t('title_label')}
        placeholder={t('title_placeholder')}
        value={title}
        onChange={(event) => {
          setTitle(event.target.value);
          if (titleError) setTitleError(false);
        }}
        error={titleError}
        helperText={titleError ? t('title_required') : undefined}
        fullWidth
      />

      <CascadingRegionSelect
        value={region}
        onChange={(next) => {
          setRegion(next);
          if (cityError && next.cityId != null) setCityError(false);
        }}
        cityError={cityError}
        cityErrorText={t('city_required')}
      />

      <AddressMapPicker
        value={pin}
        onChange={(next) => {
          setPin(next);
          if (pinError) setPinError(false);
        }}
        center={cityCentroid(region.cityId)}
        helperText={t('map_hint')}
        latLabel={t('map_lat')}
        lngLabel={t('map_lng')}
        error={pinError}
        errorText={t('map_required')}
      />

      <TextField
        label={t('line_label')}
        value={addressLine}
        onChange={(event) => {
          setAddressLine(event.target.value);
          if (lineError) setLineError(false);
        }}
        error={lineError}
        helperText={lineError ? t('line_required') : t('line_hint')}
        multiline
        minRows={2}
        fullWidth
      />

      <FormControlLabel
        control={<Switch checked={isPrimary} onChange={(event) => setIsPrimary(event.target.checked)} />}
        label={t('set_primary_toggle')}
      />

      <Stack direction="row" sx={{ gap: 1, justifyContent: 'flex-end' }}>
        {onCancel ? (
          <AppButton variant="text" onClick={onCancel} disabled={submitting}>
            {tc('cancel')}
          </AppButton>
        ) : null}
        <AppButton color="primary" variant="contained" onClick={handleSubmit} disabled={submitting}>
          {submitting ? tc('saving') : tc('save')}
        </AppButton>
      </Stack>
    </Stack>
  );
};

export default AddressForm;
