import React, { useEffect, useRef, useState } from 'react';
import {
  IonButton,
  IonButtons,
  IonContent,
  IonHeader,
  IonIcon,
  IonInput,
  IonList,
  IonModal,
  IonPage,
  IonTitle,
  IonToolbar,
} from '@ionic/react';
import {
  cameraOutline,
  chevronBackOutline,
  closeOutline,
} from 'ionicons/icons';
import { useHistory, useParams } from 'react-router-dom';
import { supabase } from '../supabase';
import { useAuth } from '../contexts/AuthContext';
import { buildCacheKey, removeCache } from '../utils/localCache';
import AvatarPicker from '../components/AvatarPicker';
import momImage from '../assets/mom.jpg';
import dadImage from '../assets/dad.jpg';
import '../styles/recipients.css';

type Params = { id?: string };

type RecipientRow = {
  id: string;
  first_name: string;
  last_name: string;
  relationship: string;
  country: string;
  city: string;
  mobile_number: string;
  photo_path: string | null;
};

const countryOptions = [
  { name: 'Zimbabwe', flag: '🇿🇼', dialCode: '+263' },
  { name: 'South Africa', flag: '🇿🇦', dialCode: '+27' },
  { name: 'Zambia', flag: '🇿🇲', dialCode: '+260' },
  { name: 'Botswana', flag: '🇧🇼', dialCode: '+267' },
  { name: 'Mozambique', flag: '🇲🇿', dialCode: '+258' },
  { name: 'United Kingdom', flag: '🇬🇧', dialCode: '+44' },
  { name: 'United States', flag: '🇺🇸', dialCode: '+1' },
  { name: 'Canada', flag: '🇨🇦', dialCode: '+1' },
  { name: 'Australia', flag: '🇦🇺', dialCode: '+61' },
];

const locationOptionsByCountry: Record<
  string,
  Array<{
    group: string;
    options: Array<{ name: string; description: string }>;
  }>
> = {
  Zimbabwe: [
    {
      group: 'Major cities',
      options: [
        { name: 'Harare', description: 'Capital city coverage' },
        { name: 'Bulawayo', description: 'City merchants and pharmacies' },
        { name: 'Mutare', description: 'Eastern Highlands coverage' },
        { name: 'Gweru', description: 'Midlands city coverage' },
      ],
    },
    {
      group: 'Towns',
      options: [
        { name: 'Chitungwiza', description: 'Harare metro support' },
        { name: 'Masvingo', description: 'Town and surrounding areas' },
        { name: 'Kwekwe', description: 'Supported collection points' },
        { name: 'Kadoma', description: 'Supported collection points' },
        { name: 'Victoria Falls', description: 'Town coverage' },
      ],
    },
    {
      group: 'Rural districts',
      options: [
        { name: 'Murehwa District', description: 'Rural collection support' },
        { name: 'Gokwe District', description: 'Rural collection support' },
        { name: 'Buhera District', description: 'Rural collection support' },
        { name: 'Zaka District', description: 'Rural collection support' },
        { name: 'Guruve District', description: 'Rural collection support' },
        {
          name: 'Tsholotsho District',
          description: 'Rural collection support',
        },
      ],
    },
  ],
  Zambia: [
    {
      group: 'Major cities',
      options: [
        { name: 'Lusaka', description: 'Capital city coverage' },
        { name: 'Ndola', description: 'Copperbelt coverage' },
        { name: 'Kitwe', description: 'Copperbelt coverage' },
        { name: 'Livingstone', description: 'Town coverage' },
      ],
    },
    {
      group: 'Rural districts',
      options: [
        { name: 'Chongwe District', description: 'Rural collection support' },
        { name: 'Monze District', description: 'Rural collection support' },
      ],
    },
  ],
  Botswana: [
    {
      group: 'Cities and towns',
      options: [
        { name: 'Gaborone', description: 'Capital city coverage' },
        { name: 'Francistown', description: 'Town coverage' },
        { name: 'Maun', description: 'Town coverage' },
      ],
    },
    {
      group: 'Rural districts',
      options: [
        { name: 'Kweneng District', description: 'Rural collection support' },
        { name: 'Central District', description: 'Rural collection support' },
      ],
    },
  ],
};

const fallbackLocationGroups = [
  {
    group: 'Supported areas',
    options: [
      { name: 'Main city', description: 'Available merchant coverage' },
      { name: 'Nearby town', description: 'Supported collection points' },
      { name: 'Rural district', description: 'Rural collection support' },
    ],
  },
];

const getCountryMeta = (countryName: string) =>
  countryOptions.find((option) => option.name === countryName) ??
  countryOptions[0];

const getLocationGroups = (countryName: string) =>
  locationOptionsByCountry[countryName] ?? fallbackLocationGroups;

const getSeededRecipientImage = (
  firstName?: string | null,
  photoPath?: string | null
) => {
  const normalizedPath = photoPath?.trim().toLowerCase();
  if (normalizedPath === 'mom.jpg' || normalizedPath === 'mum.jpg') {
    return momImage;
  }
  if (normalizedPath === 'dad.jpg' || normalizedPath === 'father.jpg') {
    return dadImage;
  }

  const normalizedName = firstName?.trim().toLowerCase();
  if (normalizedName === 'mum' || normalizedName === 'mom') {
    return momImage;
  }
  if (normalizedName === 'dad' || normalizedName === 'father') {
    return dadImage;
  }

  return null;
};

const stripDialCode = (value: string, dialCode: string) => {
  const normalizedValue = value.trim();
  if (normalizedValue.startsWith(dialCode)) {
    return normalizedValue.slice(dialCode.length).trimStart();
  }
  return normalizedValue;
};

const sanitizePhoneInput = (value: string) =>
  value.replace(/[^\d\s()-]/g, '').replace(/\s{2,}/g, ' ');

const normalizePhoneInput = (value: string) =>
  sanitizePhoneInput(value).replace(/^0+/, '');

const formatNameInput = (value: string) =>
  value
    .toLowerCase()
    .replace(
      /(^|[\s'-])([a-z])/g,
      (_match, separator: string, letter: string) =>
        `${separator}${letter.toUpperCase()}`
    );

const RecipientFormPage: React.FC = () => {
  const history = useHistory();
  const { id } = useParams<Params>();
  const { user } = useAuth();
  const isEdit = Boolean(id);

  const [firstName, setFirstName] = useState('');
  const [lastName, setLastName] = useState('');
  const [relationship, setRelationship] = useState('');
  const [country, setCountry] = useState('Zimbabwe');
  const [city, setCity] = useState('');
  const [mobileNumber, setMobileNumber] = useState('');
  const [showCountrySheet, setShowCountrySheet] = useState(false);
  const [showLocationSheet, setShowLocationSheet] = useState(false);
  const selectedCountry = getCountryMeta(country);
  const locationGroups = getLocationGroups(country);
  const [photoFile, setPhotoFile] = useState<File | null>(null);
  const [photoPreview, setPhotoPreview] = useState<string | null>(null);
  const previewObjectUrlRef = useRef<string | null>(null);
  const [existingPhotoPath, setExistingPhotoPath] = useState<string | null>(
    null
  );
  const [loading, setLoading] = useState(false);
  const [saving, setSaving] = useState(false);
  const [error, setError] = useState<string | null>(null);
  const firstNameInputRef = useRef<HTMLIonInputElement>(null);
  const lastNameInputRef = useRef<HTMLIonInputElement>(null);
  const relationshipInputRef = useRef<HTMLIonInputElement>(null);
  const mobileInputRef = useRef<HTMLIonInputElement>(null);

  useEffect(() => {
    if (isEdit) {
      void loadRecipient();
    }
  }, [id, isEdit]);

  useEffect(() => {
    return () => {
      if (previewObjectUrlRef.current) {
        URL.revokeObjectURL(previewObjectUrlRef.current);
      }
    };
  }, []);

  const handleGoBack = () => {
    if (history.length > 1) {
      history.goBack();
    } else {
      history.replace('/recipients');
    }
  };

  const showError = (message: string) => {
    setError(message);
    setTimeout(() => setError(null), 4000);
  };

  const applyRecipientToForm = async (recipient: RecipientRow) => {
    setFirstName(recipient.first_name);
    setLastName(recipient.last_name);
    setRelationship(recipient.relationship);
    setCountry(recipient.country);
    setCity(recipient.city);
    const recipientCountry = getCountryMeta(recipient.country);
    setMobileNumber(
      stripDialCode(recipient.mobile_number, recipientCountry.dialCode)
    );
    setExistingPhotoPath(recipient.photo_path);

    const seededImage = getSeededRecipientImage(
      recipient.first_name,
      recipient.photo_path
    );
    if (seededImage) {
      setPhotoPreview(seededImage);
      return;
    }

    if (!recipient.photo_path) {
      setPhotoPreview(null);
      return;
    }

    const { data: signed } = await supabase.storage
      .from('recipient-photos')
      .createSignedUrl(recipient.photo_path, 3600);
    setPhotoPreview(
      signed?.signedUrl
        ? `${signed.signedUrl}&v=${encodeURIComponent(recipient.photo_path)}`
        : null
    );
  };

  const loadRecipient = async () => {
    if (!id) return;
    setLoading(true);

    const ownerId = user?.id ?? '00000000-0000-0000-0000-000000000000';

    const { data, error: loadError } = await supabase
      .from('recipients')
      .select(
        'id,first_name,last_name,relationship,country,city,mobile_number,photo_path'
      )
      .eq('id', id)
      .eq('user_id', ownerId)
      .single();

    if (loadError || !data) {
      showError(loadError?.message ?? 'Recipient not found');
      setLoading(false);
      history.replace('/recipients');
      return;
    }

    const recipient = data as RecipientRow;
    await applyRecipientToForm(recipient);
    setLoading(false);
  };

  const handlePhotoChange = (event: React.ChangeEvent<HTMLInputElement>) => {
    const file = event.target.files?.[0];
    if (!file) return;

    if (previewObjectUrlRef.current) {
      URL.revokeObjectURL(previewObjectUrlRef.current);
    }

    const objectUrl = URL.createObjectURL(file);
    previewObjectUrlRef.current = objectUrl;
    setPhotoFile(file);
    setPhotoPreview(objectUrl);
  };

  const handleSubmit = async (event: React.FormEvent) => {
    event.preventDefault();
    if (!user) {
      showError('Please sign in again to save this loved one');
      return;
    }

    const payload = {
      first_name: firstName.trim(),
      last_name: lastName.trim(),
      relationship: relationship.trim(),
      country: country.trim(),
      city: city.trim(),
      mobile_number:
        `${selectedCountry.dialCode} ${mobileNumber.trim()}`.trim(),
      updated_at: new Date().toISOString(),
    };

    if (
      !payload.first_name ||
      !payload.last_name ||
      !payload.relationship ||
      !payload.country ||
      !payload.city ||
      !payload.mobile_number
    ) {
      showError('Please complete all required fields');
      return;
    }

    setSaving(true);
    setError(null);

    let photoPath = existingPhotoPath;
    if (photoFile) {
      const extension = photoFile.name.split('.').pop() || 'jpg';
      photoPath = `${user.id}/${Date.now()}.${extension}`;
      const { error: uploadError } = await supabase.storage
        .from('recipient-photos')
        .upload(photoPath, photoFile);

      if (uploadError) {
        showError(uploadError.message);
        setSaving(false);
        return;
      }
    }

    const recipientsCacheKey = buildCacheKey(user.id, 'recipientsList');

    if (isEdit && id) {
      const { error: updateError } = await supabase
        .from('recipients')
        .update({ ...payload, photo_path: photoPath })
        .eq('id', id)
        .eq('user_id', user.id);

      if (updateError) {
        showError(updateError.message);
        setSaving(false);
        return;
      }

      await Promise.all([
        removeCache(recipientsCacheKey),
        removeCache(buildCacheKey(user.id, `recipient_${id}`)),
      ]);
      setSaving(false);
      history.push(`/recipients/${id}`);
      return;
    }

    const { data, error: insertError } = await supabase
      .from('recipients')
      .insert({
        user_id: user.id,
        ...payload,
        photo_path: photoPath,
      })
      .select('id')
      .single();

    if (insertError || !data) {
      showError(insertError?.message ?? 'Could not create recipient');
      setSaving(false);
      return;
    }

    await removeCache(recipientsCacheKey);
    setSaving(false);
    history.replace(`/recipients/${data.id}`);
  };

  const initials = `${firstName.charAt(0)}${lastName.charAt(0)}`.toUpperCase();

  return (
    <IonPage style={{ backgroundColor: '#fafafa' }}>
      <IonHeader className="ion-no-border">
        <IonToolbar
          style={
            {
              '--background': '#fafafa',
              '--border-width': '0px',
              '--color': '#111827',
            } as React.CSSProperties
          }
        >
          <IonButtons slot="start">
            <IonButton
              className="recipients-back-button"
              fill="clear"
              onClick={handleGoBack}
              aria-label="Go back"
            >
              <IonIcon icon={chevronBackOutline} slot="icon-only" />
            </IonButton>
          </IonButtons>
          <IonTitle style={{ fontSize: '18px', fontWeight: 700 }}>
            {isEdit ? 'Edit loved one' : 'Add loved one'}
          </IonTitle>
        </IonToolbar>
      </IonHeader>

      <IonContent
        style={
          {
            '--background': '#fafafa',
            '--padding-start': '0px',
            '--padding-end': '0px',
            '--padding-top': '8px',
            '--padding-bottom': 'calc(32px + var(--ion-safe-area-bottom, 0px))',
          } as React.CSSProperties
        }
      >
        <form onSubmit={handleSubmit}>
          <div className="recipient-form-card">
            <div className="rf-photo-picker">
              <IonIcon icon={cameraOutline} style={{ display: 'none' }} />
              <AvatarPicker
                previewUrl={photoPreview}
                onFileChange={handlePhotoChange}
                initials={initials || undefined}
                disabled={loading || saving}
              />
            </div>

            <button
              type="button"
              className="rf-input-shell rf-text-shell"
              onClick={() => void firstNameInputRef.current?.setFocus()}
              disabled={loading || saving}
              aria-label="Enter first name"
            >
              <span className="rf-field-label">First name</span>
              <IonInput
                ref={firstNameInputRef}
                className="rf-field"
                type="text"
                placeholder="Sarah"
                value={firstName}
                disabled={loading || saving}
                onIonInput={(event) =>
                  setFirstName(formatNameInput(event.detail.value ?? ''))
                }
              />
            </button>
            <button
              type="button"
              className="rf-input-shell rf-text-shell"
              onClick={() => void lastNameInputRef.current?.setFocus()}
              disabled={loading || saving}
              aria-label="Enter last name"
            >
              <span className="rf-field-label">Last name</span>
              <IonInput
                ref={lastNameInputRef}
                className="rf-field"
                type="text"
                placeholder="Moyo"
                value={lastName}
                disabled={loading || saving}
                onIonInput={(event) =>
                  setLastName(formatNameInput(event.detail.value ?? ''))
                }
              />
            </button>
            <button
              type="button"
              className="rf-input-shell rf-text-shell"
              onClick={() => void relationshipInputRef.current?.setFocus()}
              disabled={loading || saving}
              aria-label="Enter relationship"
            >
              <span className="rf-field-label">Relationship</span>
              <IonInput
                ref={relationshipInputRef}
                className="rf-field"
                type="text"
                placeholder="Mum, Brother, Aunt"
                value={relationship}
                disabled={loading || saving}
                onIonInput={(event) =>
                  setRelationship(formatNameInput(event.detail.value ?? ''))
                }
              />
            </button>
            <button
              type="button"
              className="rf-country-trigger"
              onClick={() => setShowCountrySheet(true)}
              disabled={loading || saving}
              aria-label="Select country"
            >
              <span className="rf-country-label">Country</span>
              <span className="rf-country-value-row">
                <span className="rf-country-value">
                  {`${selectedCountry.flag} ${selectedCountry.name} (${selectedCountry.dialCode})`}
                </span>
                <IonIcon
                  icon={chevronBackOutline}
                  className="rf-country-chevron"
                />
              </span>
            </button>
            <button
              type="button"
              className="rf-country-trigger"
              onClick={() => setShowLocationSheet(true)}
              disabled={loading || saving}
              aria-label="Select recipient location"
            >
              <span className="rf-country-label">Location</span>
              <span className="rf-country-value-row">
                <span
                  className={`rf-country-value${city ? '' : ' is-placeholder'}`}
                >
                  {city || 'City, town, or rural area'}
                </span>
                <IonIcon
                  icon={chevronBackOutline}
                  className="rf-country-chevron"
                />
              </span>
            </button>
            <button
              type="button"
              className="rf-input-shell rf-phone-shell"
              onClick={() => void mobileInputRef.current?.setFocus()}
              disabled={loading || saving}
              aria-label="Enter mobile number"
            >
              <span className="rf-field-label">Mobile number</span>
              <div className="rf-phone-row">
                <div className="rf-phone-prefix" aria-hidden="true">
                  <span className="rf-phone-flag">{selectedCountry.flag}</span>
                  <span className="rf-phone-code">
                    {selectedCountry.dialCode}
                  </span>
                </div>
                <IonInput
                  ref={mobileInputRef}
                  className="rf-field rf-phone-field"
                  type="tel"
                  inputMode="tel"
                  placeholder="77 123 4567"
                  value={mobileNumber}
                  disabled={loading || saving}
                  onIonInput={(event) =>
                    setMobileNumber(
                      normalizePhoneInput(event.detail.value ?? '')
                    )
                  }
                />
              </div>
            </button>
            {error && (
              <p style={{ margin: 0, color: '#dc2626', fontSize: '13px' }}>
                {error}
              </p>
            )}
          </div>

          <div className="rf-actions">
            <IonButton
              type="submit"
              expand="block"
              className="rf-submit-btn"
              disabled={loading || saving}
            >
              {saving ? 'Saving...' : isEdit ? 'Save changes' : 'Add loved one'}
            </IonButton>
          </div>
        </form>

        <IonModal
          isOpen={showCountrySheet}
          onDidDismiss={() => setShowCountrySheet(false)}
          initialBreakpoint={1}
          breakpoints={[0, 1]}
          handle={true}
          className="country-sheet-modal"
        >
          <div className="country-sheet-shell">
            <div className="country-sheet-header">
              <h2>Select country</h2>
              <IonButton
                fill="clear"
                className="country-sheet-close"
                onClick={() => setShowCountrySheet(false)}
                aria-label="Close country selector"
              >
                <IonIcon icon={closeOutline} slot="icon-only" />
              </IonButton>
            </div>
            <div className="country-sheet-scroll">
              <IonList lines="none" className="country-sheet-list">
                {countryOptions.map((option) => {
                  const isSelected = option.name === country;
                  return (
                    <button
                      key={option.name}
                      type="button"
                      className={`country-sheet-option${isSelected ? ' is-selected' : ''}`}
                      onClick={() => {
                        setCountry(option.name);
                        setCity('');
                        setShowCountrySheet(false);
                      }}
                    >
                      <span className="country-sheet-option-text">
                        <span className="country-sheet-flag">
                          {option.flag}
                        </span>
                        <span className="country-sheet-name">
                          {option.name}
                        </span>
                        <span className="country-sheet-code">
                          ({option.dialCode})
                        </span>
                      </span>
                    </button>
                  );
                })}
              </IonList>
            </div>
          </div>
        </IonModal>

        <IonModal
          isOpen={showLocationSheet}
          onDidDismiss={() => setShowLocationSheet(false)}
          initialBreakpoint={1}
          breakpoints={[0, 1]}
          handle={true}
          className="country-sheet-modal"
        >
          <div className="country-sheet-shell">
            <div className="country-sheet-header">
              <h2>Select location</h2>
              <IonButton
                fill="clear"
                className="country-sheet-close"
                onClick={() => setShowLocationSheet(false)}
                aria-label="Close location selector"
              >
                <IonIcon icon={closeOutline} slot="icon-only" />
              </IonButton>
            </div>
            <div className="country-sheet-scroll">
              <div className="location-sheet-helper">
                Choose a city, town, or rural district where support collection
                is available.
              </div>
              {locationGroups.map((group) => (
                <div key={group.group} className="location-sheet-group">
                  <p className="location-sheet-group-title">{group.group}</p>
                  {group.options.map((option) => {
                    const isSelected = option.name === city;
                    return (
                      <button
                        key={option.name}
                        type="button"
                        className={`country-sheet-option location-sheet-option${isSelected ? ' is-selected' : ''}`}
                        onClick={() => {
                          setCity(option.name);
                          setShowLocationSheet(false);
                        }}
                      >
                        <span className="location-sheet-option-text">
                          <span className="location-sheet-name">
                            {option.name}
                          </span>
                          <span className="location-sheet-description">
                            {option.description}
                          </span>
                        </span>
                      </button>
                    );
                  })}
                </div>
              ))}
            </div>
          </div>
        </IonModal>
      </IonContent>
    </IonPage>
  );
};

export default RecipientFormPage;
