import { useEffect, useMemo, useState } from 'react';
import { StyleSheet, Text, View } from 'react-native';
import { NativeStackScreenProps } from '@react-navigation/native-stack';
import api from '../../core/api';
import { resourceConfigs } from '../../constants/resourceConfigs';
import { fieldsForTab, resolveFormTabs } from '../../constants/formTabsConfig';
import { useSelectOptions } from '../../hooks/useSelectOptions';
import { AppStackParamList } from '../../navigation/types';
import { ScreenLayout } from '../../components/ui/ScreenLayout';
import { FormField, type FieldConfig } from '../../components/ui/FormField';
import { FormTabPanel, FormTabs } from '../../components/ui/FormTabs';
import { FormActionsFooter } from '../../components/ui/FormActionsFooter';
import { colors, radii, spacing } from '../../constants/theme';
import { useSubscriptionRestriction } from '../../hooks/useSubscriptionRestriction';
import { SKIP_FORM_TYPES } from './ResourceListScreen';
import { normalizeBusinessHours, normalizeSwitchList } from '../../utils/formValueHelpers';

type Props = NativeStackScreenProps<AppStackParamList, 'ResourceForm'>;

function normalizeFormRecord(resource: string, record: Record<string, unknown>): Record<string, unknown> {
  const next = { ...record };

  if (resource === 'staff' || resource === 'branches') {
    if ('availability' in next) next.availability = normalizeBusinessHours(next.availability);
  }

  if (resource === 'staff') {
    if ('permissions' in next) next.permissions = normalizeSwitchList(next.permissions);
    if ('service_ids' in next) next.service_ids = normalizeSwitchList(next.service_ids).map(Number);
  }

  if (resource === 'services') {
    if ('staff_ids' in next) {
      next.staff_ids = normalizeSwitchList(next.staff_ids).map(Number);
    }
    if ('quantity_on_hand' in next && next.quantity_on_hand !== null && next.quantity_on_hand !== '') {
      next.quantity_on_hand = Number(next.quantity_on_hand) || 0;
    }
  }

  return next;
}

function defaultFieldValue(field: FieldConfig): unknown {
  if (field.type === 'checkbox') return false;
  if (field.type === 'business-hours') return {};
  if (field.type === 'switch-list') return [];
  if (field.key === 'status' && field.options?.length) {
    const first = field.options[0];
    return typeof first === 'string' ? first : first.value;
  }
  if (field.key === 'user_role') return 'staff';
  if (field.key === 'quantity_on_hand') return 0;
  if (field.key === 'type') return 'service';
  return '';
}

export function ResourceFormScreen({ navigation, route }: Props) {
  const { readOnly, runIfAllowed } = useSubscriptionRestriction();
  const { resource, id } = route.params;
  const configs = resourceConfigs as Record<string, typeof resourceConfigs.customers>;
  const config = configs[resource] || resourceConfigs.customers;
  const configFields = useMemo(() => (config.fields || []) as FieldConfig[], [config]);
  const fields = configFields.filter(
    (f) => !SKIP_FORM_TYPES.has(f.type || ''),
  );
  const { options: loadedOptions, loadSources, getOptions } = useSelectOptions();
  const [form, setForm] = useState<Record<string, unknown>>({});
  const [loading, setLoading] = useState(!!id);
  const [saving, setSaving] = useState(false);
  const [error, setError] = useState('');
  const [activeTab, setActiveTab] = useState('');

  useEffect(() => {
    void loadSources(
      configFields.map((field) => (
        field.source ? { source: field.source, params: field.sourceParams } : null
      )),
    );
  }, [configFields, loadSources]);

  useEffect(() => {
    if (id) {
      (async () => {
        try {
          const { data } = await api.get(`/${resource}/${id}`);
          setForm(normalizeFormRecord(resource, (data.data || data) as Record<string, unknown>));
        } catch {
          setError('Unable to load record.');
        } finally {
          setLoading(false);
        }
      })();
      return;
    }

    const defaults = configFields.reduce<Record<string, unknown>>((acc, field) => {
      if (!SKIP_FORM_TYPES.has(field.type || '')) {
        acc[field.key] = defaultFieldValue(field);
      }
      return acc;
    }, {});
    setForm(normalizeFormRecord(resource, defaults));
    setLoading(false);
  }, [id, resource, configFields]);

  const resolvedFields = useMemo(() => fields.map((field) => ({
    ...field,
    options: field.source
      ? getOptions(field.source, field.sourceParams || {})
      : field.options,
  })), [fields, getOptions, loadedOptions]);

  const visibleFields = useMemo(() => resolvedFields.filter((field) => {
    if (resource !== 'services') return true;
    if (field.key === 'track_inventory' || field.key === 'reorder_level' || field.key === 'quantity_on_hand') {
      return String(form.type || 'service').toLowerCase() === 'product';
    }
    return true;
  }), [resolvedFields, form.type, resource]);

  const formTabs = useMemo(
    () => resolveFormTabs(resource, visibleFields),
    [resource, visibleFields],
  );

  useEffect(() => {
    if (!formTabs?.length) {
      setActiveTab('');
      return;
    }
    if (!formTabs.some((tab) => tab.key === activeTab)) {
      setActiveTab(formTabs[0].key);
    }
  }, [activeTab, formTabs]);

  const save = async () => {
    if (readOnly || !runIfAllowed(() => {})) {
      return;
    }
    setSaving(true);
    setError('');
    try {
      const payload = { ...form };
      if (resource === 'staff' && Array.isArray(payload.service_ids)) {
        payload.service_ids = payload.service_ids.map(Number);
      }
      if (resource === 'services') {
        if (Array.isArray(payload.staff_ids)) {
          payload.staff_ids = payload.staff_ids.map(Number);
        }
        if (String(payload.type || 'service').toLowerCase() === 'service') {
          delete payload.quantity_on_hand;
        } else if (payload.quantity_on_hand !== undefined && payload.quantity_on_hand !== '') {
          payload.quantity_on_hand = Number(payload.quantity_on_hand) || 0;
        }
      }

      if (id) {
        await api.put(`/${resource}/${id}`, payload);
      } else {
        await api.post(`/${resource}`, payload);
      }
      navigation.goBack();
    } catch (e: unknown) {
      const err = e as { response?: { data?: { message?: string } } };
      setError(err.response?.data?.message || 'Save failed.');
    } finally {
      setSaving(false);
    }
  };

  const updateField = (field: FieldConfig, value: unknown) => {
    setForm((prev) => {
      const next = { ...prev, [field.key]: value };
      if (resource === 'services' && field.key === 'type' && String(value).toLowerCase() === 'service') {
        next.track_inventory = false;
        next.reorder_level = 0;
        next.quantity_on_hand = 0;
      }
      return next;
    });
  };

  const renderFields = (tabFields: FieldConfig[]) => tabFields.map((field) => (
    <FormField
      key={field.key}
      field={field}
      value={form[field.key]}
      formData={form}
      resource={resource}
      recordId={id}
      onChange={(v) => updateField(field, v)}
    />
  ));

  return (
    <ScreenLayout
      title={`${id ? 'Edit' : 'Add'} ${config.singular}`}
      subtitle={config.description}
      footer={readOnly ? undefined : (
        <FormActionsFooter
          submitLabel={id ? 'Update' : 'Add'}
          onSubmit={save}
          onCancel={() => navigation.goBack()}
          loading={saving || loading}
        />
      )}
    >
      {error ? <Text style={styles.error}>{error}</Text> : null}
      <View style={styles.formCard}>
        {formTabs ? (
          <>
            <FormTabs tabs={formTabs} activeTab={activeTab} onChange={setActiveTab} />
            {formTabs.map((tab) => (
              <FormTabPanel key={tab.key} visible={activeTab === tab.key} tab={tab}>
                {renderFields(fieldsForTab(tab.key, formTabs, visibleFields))}
              </FormTabPanel>
            ))}
          </>
        ) : (
          renderFields(visibleFields)
        )}
      </View>
    </ScreenLayout>
  );
}

const styles = StyleSheet.create({
  formCard: {
    backgroundColor: colors.surface,
    borderColor: colors.border,
    borderRadius: radii.lg,
    borderWidth: 1,
    marginBottom: spacing.md,
    padding: spacing.md,
  },
  error: { color: colors.danger, marginBottom: spacing.md },
});
