import { useCallback, useEffect, useState } from 'react';
import { ActivityIndicator, Alert, StyleSheet, Text, View } from 'react-native';
import type { NavigationProp } from '@react-navigation/native';
import { NativeStackScreenProps } from '@react-navigation/native-stack';
import api from '../../core/api';
import { resourceConfigs } from '../../constants/resourceConfigs';
import { AppStackParamList } from '../../navigation/types';
import { ScreenLayout } from '../../components/ui/ScreenLayout';
import { SearchBar } from '../../components/ui/SearchBar';
import { RecordCard } from '../../components/ui/RecordCard';
import { AppButton } from '../../components/ui/AppButton';
import { colors, spacing } from '../../constants/theme';
import { useAuth } from '../../context/AuthContext';
import { useSubscriptionRestriction } from '../../hooks/useSubscriptionRestriction';
import { EmptyState } from '../../components/ui/EmptyState';
import { buildRecordPresentation } from '../../utils/resourceListDisplay';
import { ServicesFilterBar, type ServiceListFilters } from '../../components/services/ServicesFilterBar';
import { useSelectOptions } from '../../hooks/useSelectOptions';
import { defaultServiceExportColumns, downloadResourceExport } from '../../services/resourceExport';

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

export type ResourceListInnerProps = {
  resource: string;
  navigation: NavigationProp<AppStackParamList>;
};

const SKIP_FORM_TYPES = new Set([
  'photo',
  'attachments',
  'prescription-medications',
  'country-select',
  'state-select',
  'city-select',
  'color',
  'json',
  'relation',
]);

export function ResourceListScreen({ navigation, route }: Props) {
  return <ResourceListInner navigation={navigation} resource={route.params.resource} />;
}

export function ResourceListInner({ navigation, resource }: ResourceListInnerProps) {
  const configs = resourceConfigs as Record<string, typeof resourceConfigs.customers>;
  const config = configs[resource] || resourceConfigs.customers;
  const { portal } = useAuth();
  const { readOnly: subscriptionReadOnly, runIfAllowed } = useSubscriptionRestriction();
  const readOnly = subscriptionReadOnly || (portal === 'customer' && resource !== 'patients');
  const [search, setSearch] = useState('');
  const [page, setPage] = useState(1);
  const [records, setRecords] = useState<Record<string, unknown>[]>([]);
  const [lastPage, setLastPage] = useState(1);
  const [loading, setLoading] = useState(true);
  const [error, setError] = useState('');
  const [showTrashed, setShowTrashed] = useState(false);
  const [serviceFilters, setServiceFilters] = useState<ServiceListFilters>({
    type: '',
    staff_id: '',
    low_stock: false,
  });
  const [exporting, setExporting] = useState(false);
  const { getOptions, loadSources } = useSelectOptions();

  const listParams = useCallback(() => {
    if (resource !== 'services' || showTrashed) {
      return { search, page, per_page: 15, trashed: showTrashed ? 1 : undefined };
    }

    return {
      search,
      page,
      per_page: 15,
      type: serviceFilters.type || undefined,
      staff_id: serviceFilters.staff_id || undefined,
      low_stock: serviceFilters.low_stock ? 1 : undefined,
    };
  }, [resource, search, page, showTrashed, serviceFilters]);

  const load = useCallback(async () => {
    setLoading(true);
    setError('');
    try {
      const { data } = await api.get(`/${resource}`, {
        params: listParams(),
      });
      setRecords(data.data || data);
      setLastPage(data.last_page || 1);
    } catch (e: unknown) {
      const err = e as { response?: { data?: { message?: string } } };
      setError(err.response?.data?.message || 'Unable to load records.');
    } finally {
      setLoading(false);
    }
  }, [resource, listParams]);

  useEffect(() => {
    if (resource === 'services') {
      void loadSources([{ source: 'staff-doctors' }]);
    }
  }, [resource, loadSources]);

  useEffect(() => {
    load();
  }, [load]);

  useEffect(() => {
    const unsub = navigation.addListener('focus', load);
    return unsub;
  }, [navigation, load]);

  const recordPresentation = (row: Record<string, unknown>) => buildRecordPresentation(
    resource,
    row,
    (config.columns || []) as { key: string; label?: string; type?: string }[],
  );

  const applyServiceFilters = (next?: ServiceListFilters) => {
    if (next) {
      setServiceFilters(next);
    }
    setPage(1);
  };

  const clearServiceFilters = () => {
    applyServiceFilters({ type: '', staff_id: '', low_stock: false });
  };

  const exportServices = async () => {
    setExporting(true);
    setError('');
    try {
      await downloadResourceExport('services', {
        columns: defaultServiceExportColumns,
        format: 'csv',
        search: search || undefined,
        type: serviceFilters.type || undefined,
        staff_id: serviceFilters.staff_id || undefined,
        low_stock: serviceFilters.low_stock ? 1 : undefined,
      });
    } catch (e: unknown) {
      const err = e as { message?: string; response?: { data?: { message?: string } } };
      setError(err.message || err.response?.data?.message || 'Unable to export records.');
    } finally {
      setExporting(false);
    }
  };

  const onDelete = (row: Record<string, unknown>) => {
    if (!runIfAllowed(() => {})) {
      return;
    }
    Alert.alert('Delete', 'Remove this record?', [
      { text: 'Cancel', style: 'cancel' },
      {
        text: 'Delete',
        style: 'destructive',
        onPress: async () => {
          await api.delete(`/${resource}/${row.id}`);
          load();
        },
      },
    ]);
  };

  return (
    <ScreenLayout
      title={config.title}
      subtitle={config.description}
      onRefresh={load}
      refreshing={loading}
      actions={
        !readOnly && !showTrashed ? (
          <AppButton
            label="Add"
            icon="add"
            onPress={() => navigation.navigate('ResourceForm', { resource })}
          />
        ) : undefined
      }
    >
      {!readOnly ? (
        <View style={styles.toolbar}>
          <AppButton
            label={showTrashed ? 'Active' : 'Trash'}
            icon={showTrashed ? 'back' : 'delete'}
            variant="secondary"
            onPress={() => {
              setShowTrashed(!showTrashed);
              setPage(1);
            }}
          />
        </View>
      ) : null}
      <SearchBar
        value={search}
        onChangeText={setSearch}
        onSubmit={() => {
          setPage(1);
          load();
        }}
        placeholder={`Search ${config.title.toLowerCase()}`}
      />
      {resource === 'services' && !showTrashed && !readOnly ? (
        <ServicesFilterBar
          filters={serviceFilters}
          staffOptions={getOptions('staff-doctors')}
          exporting={exporting}
          onChange={(patch) => setServiceFilters((current) => ({ ...current, ...patch }))}
          onApply={applyServiceFilters}
          onClear={clearServiceFilters}
          onExport={exportServices}
        />
      ) : null}
      {error ? <Text style={styles.error}>{error}</Text> : null}
      {loading && !records.length ? (
        <ActivityIndicator color={colors.primary} style={{ marginTop: 24 }} />
      ) : records.length ? (
        records.map((row) => {
          const presentation = recordPresentation(row);
          return (
          <RecordCard
            key={String(row.id)}
            title={presentation.title}
            subtitle={presentation.subtitle}
            badge={presentation.badge}
            lowStock={presentation.lowStock}
            onPress={() => {
              if (resource === 'patients') {
                navigation.navigate('PatientDetail', { id: Number(row.id) });
                return;
              }
              if (!readOnly) {
                navigation.navigate('ResourceForm', { resource, id: Number(row.id) });
              }
            }}
            actions={
              readOnly
                ? resource === 'patients'
                  ? [{ icon: 'view', label: 'View', onPress: () => navigation.navigate('PatientDetail', { id: Number(row.id) }) }]
                  : undefined
                : [
                    {
                      icon: 'edit',
                      label: 'Edit',
                      onPress: () => navigation.navigate('ResourceForm', { resource, id: Number(row.id) }),
                    },
                    ...(row.is_system_default
                      ? []
                      : [{ icon: 'delete', label: 'Delete', onPress: () => onDelete(row), variant: 'danger' as const }]),
                  ]
            }
          />
          );
        })
      ) : (
        <EmptyState icon="search" title="No records found" message={`No ${config.title.toLowerCase()} match your filters.`} />
      )}
      {lastPage > 1 ? (
        <View style={styles.pager}>
          <AppButton
            label="Previous"
            icon="back"
            variant="secondary"
            disabled={page <= 1}
            onPress={() => setPage((p) => p - 1)}
          />
          <Text style={styles.pageText}>
            {page} / {lastPage}
          </Text>
          <AppButton
            label="Next"
            icon="forward"
            variant="secondary"
            disabled={page >= lastPage}
            onPress={() => setPage((p) => p + 1)}
          />
        </View>
      ) : null}
    </ScreenLayout>
  );
}

const styles = StyleSheet.create({
  toolbar: { marginBottom: spacing.sm },
  error: { color: colors.danger, marginBottom: spacing.md },
  pager: { flexDirection: 'row', alignItems: 'center', justifyContent: 'space-between', marginTop: spacing.md },
  pageText: { color: colors.textMuted },
});

export { SKIP_FORM_TYPES };
