import React, { useState, useEffect, useCallback } from 'react';
import {
  View,
  Text,
  StyleSheet,
  FlatList,
  TouchableOpacity,
  Alert,
  ScrollView,
  Dimensions
} from 'react-native';
import { Ionicons } from '@expo/vector-icons';
import { useFocusEffect } from '@react-navigation/native';
import { offlineMapManager } from './OfflineMapManager';
import { NAVIGATION_PAGES } from 'src/types';
import { formatBytes } from './formatters';
import { useSubscription } from './useSubscription';
import { Header, Input, Loading, PageWrapper, WarningModal } from 'src/components';
import { Colors } from 'src/theme';
import { getFontSize } from 'src/utils';
import * as Progress from 'react-native-progress';
import { storage, StoreType } from 'src/storage';
import EditIcon from 'assets/icons/travels-screens/pen-to-square.svg';
import { usePostGetLastMapUpdateDateQuery } from '@api/maps';

const OFFLINE_MAPS_KEY = 'offline_maps';

export default function OfflineMapsScreen({ navigation }: { navigation: any }) {
  const token = storage.get('token', StoreType.STRING) as string;
  const contentWidth = Dimensions.get('window').width * 0.9;
  const { data: lastMapUpdate } = usePostGetLastMapUpdateDateQuery(token, true);
  const [maps, setMaps] = useState([]);
  const [editingId, setEditingId] = useState(null);
  const [editingName, setEditingName] = useState('');
  const [loading, setLoading] = useState(true);
  const { isPremium } = useSubscription();
  const [lastUpdate, setLastUpdate] = useState<string>(new Date().toISOString().slice(0, 10));
  const [modalState, setModalState] = useState({
    visible: false,
    type: 'confirm',
    action: () => {},
    message: '',
    title: ''
  });

  useEffect(() => {
    offlineMapManager.init();
  }, []);

  useEffect(() => {
    if (lastMapUpdate) {
      setLastUpdate(lastMapUpdate.last_update);
    }
  }, [lastMapUpdate]);

  useEffect(() => {
    if (lastUpdate) {
      loadMaps();
    }
  }, [lastUpdate]);

  useEffect(() => {
    const intervalId = setInterval(() => {
      const mapsString = storage.get(OFFLINE_MAPS_KEY, StoreType.STRING) as string;
      try {
        if (!mapsString) return;
        const parsedMaps = JSON.parse(mapsString);
        if (
          parsedMaps.some((map: any) => map.status === 'downloading') ||
          JSON.stringify(maps) !== mapsString
        ) {
          setMaps(parsedMaps);
        }
      } catch (e) {
        console.warn('Invalid OFFLINE_MAPS_KEY JSON', e);
      }
    }, 1000);

    return () => clearInterval(intervalId);
  }, [maps]);

  const loadMaps = useCallback(async () => {
    try {
      setLoading(true);
      const savedMapsString = storage.get(OFFLINE_MAPS_KEY, StoreType.STRING) as string;
      const savedMaps = savedMapsString ? JSON.parse(savedMapsString) : [];

      const availablePacks = await offlineMapManager.getPacks();
      const availablePackIds = availablePacks.map((pack) => pack.name);

      const updatedMaps = savedMaps.map((map: any) => {
        if (map.status === 'downloading' && map.progress < 100) {
          return map;
        }

        if (map.status === 'downloading' && map.progress >= 100) {
          return {
            ...map,
            status: 'valid'
          };
        }

        const mapUpdateDate = new Date(map.updatedAt).toISOString().slice(0, 10);
        if (mapUpdateDate < lastUpdate) {
          return {
            ...map,
            status: 'invalid'
          };
        }

        return {
          ...map,
          status: isPremium && availablePackIds.includes(map.id) ? 'valid' : 'invalid'
        };
      });

      setMaps(updatedMaps);

      storage.set(OFFLINE_MAPS_KEY, JSON.stringify(updatedMaps));
    } catch (error) {
      console.error('Error loading offline maps:', error);
    } finally {
      setLoading(false);
    }
  }, [isPremium, lastUpdate]);

  useFocusEffect(
    useCallback(() => {
      loadMaps();
    }, [loadMaps])
  );

  useEffect(() => {
    if (isPremium) {
      restoreOfflineMaps();
    } else {
      invalidateMaps();
    }
  }, [isPremium]);

  const hasDownloadingMaps = () => {
    if (!maps) return false;
    return maps.some((map) => map?.status === 'downloading' && map?.progress < 100);
  };

  const closeModal = () => {
    setModalState({
      visible: false,
      type: 'confirm',
      action: () => {},
      message: '',
      title: ''
    });
  };

  const restoreOfflineMaps = async () => {
    try {
      const savedMapsString = storage.get(OFFLINE_MAPS_KEY, StoreType.STRING) as string;
      if (!savedMapsString) return;

      const savedMaps = JSON.parse(savedMapsString);

      setLoading(true);

      for (const map of savedMaps.filter((m: any) => m.status === 'invalid' && m.progress < 100)) {
        try {
          const pack = await offlineMapManager.getPack(map.id);
          if (!pack) {
            if (map.bounds) {
              await offlineMapManager.resumePackDownload(map.id);
            }
          }
        } catch (error) {
          console.error(`Error checking pack ${map.id}:`, error);
        }
      }

      loadMaps();
    } catch (error) {
      console.error('Error restoring offline maps:', error);
    }
  };

  const invalidateMaps = async () => {
    try {
      const packs = await offlineMapManager.getPacks();
      for (const pack of packs) {
        await offlineMapManager.invalidatePack(pack.name);
      }

      loadMaps();
    } catch (error) {
      console.error('Error invalidating maps:', error);
    }
  };

  const handleDelete = (id: string, name: string) => {
    setModalState({
      visible: true,
      type: 'delete',
      action: async () => {
        try {
          const mapsString = storage.get(OFFLINE_MAPS_KEY, StoreType.STRING) as string;
          const maps = mapsString ? JSON.parse(mapsString) : [];
          const map = maps.find((m: any) => m.id === id);

          if (map && map.status === 'downloading') {
            await offlineMapManager.cancelPackDownload(id);
          } else {
            await offlineMapManager.deletePack(id);
          }

          const updatedMaps = maps.filter((map: any) => map.id !== id);
          storage.set(OFFLINE_MAPS_KEY, JSON.stringify(updatedMaps));

          setMaps(updatedMaps);
        } catch (error) {
          console.error('Error deleting offline map:', error);
          Alert.alert('Error', 'Failed to delete offline map');
        }
      },
      message: `Are you sure you want to delete "${name}"?`,
      title: 'Delete Offline Map'
    });
  };

  const handleUpdate = async (map: any) => {
    try {
      await offlineMapManager.updatePack(
        map.id,
        (progress: any) => {},
        (error: any) => {
          console.error(`Error updating map ${map.id}:`, error);
        }
      );

      loadMaps();
    } catch (error) {
      console.error('Error updating offline map:', error);
    }
  };

  const handleEditName = (id, currentName) => {
    setEditingId(id);
    setEditingName(currentName);
  };

  const handleSaveName = () => {
    if (!editingName.trim()) {
      Alert.alert('Error', 'Map name cannot be empty');
      return;
    }

    const updatedMaps = maps.map((map: any) =>
      map.id === editingId ? { ...map, name: editingName } : map
    );

    storage.set(OFFLINE_MAPS_KEY, JSON.stringify(updatedMaps));
    setMaps(updatedMaps);
    setEditingId(null);
    setEditingName('');
  };

  const handleCancelEdit = () => {
    setEditingId(null);
    setEditingName('');
  };

  const renderItem = ({ item }: { item: any }) => (
    <View style={styles.mapItem}>
      {editingId === item.id ? (
        <View style={styles.editNameContainer}>
          <View style={{ flex: 1 }}>
            <Input
              value={editingName}
              onChange={setEditingName}
              inputMode="text"
              formikError={!editingName.length}
              autoFocus
            />
          </View>
          <TouchableOpacity onPress={handleSaveName} style={styles.iconButton}>
            <Ionicons name="checkmark" size={22} color={Colors.DARK_BLUE} />
          </TouchableOpacity>
          <TouchableOpacity onPress={handleCancelEdit} style={styles.iconButton}>
            <Ionicons name="close" size={22} color={Colors.RED} />
          </TouchableOpacity>
        </View>
      ) : (
        <View style={styles.mapInfoContainer}>
          <Text style={styles.mapName}>{item.name}</Text>
          {/* <TouchableOpacity
            onPress={() => handleEditName(item.id, item.name)}
            style={styles.iconButton}
          >
            <EditIcon height={16} width={16} color={Colors.DARK_BLUE} />
          </TouchableOpacity> */}
        </View>
      )}

      <View style={{ flexDirection: 'row', alignItems: 'center', justifyContent: 'space-between' }}>
        <View style={{ gap: 2 }}>
          <Text style={styles.mapDetails}>Size: {formatBytes(item.size)}</Text>
          <Text style={styles.mapDetails}>
            Updated: {new Date(item.updatedAt).toLocaleDateString()}
          </Text>
        </View>

        <TouchableOpacity
          onPress={() => handleDelete(item.id, item.name)}
          style={[styles.actionButton, styles.deleteButton]}
        >
          <Text style={styles.actionButtonText}>Delete</Text>
        </TouchableOpacity>
      </View>

      {item.status === 'downloading' && item.progress < 100 && (
        <View style={styles.downloadProgressContainer}>
          <Progress.Bar
            progress={item.progress / 100}
            width={contentWidth - 32 - 32}
            color={Colors.DARK_BLUE}
            borderWidth={0}
            borderRadius={5}
            unfilledColor="rgba(0, 0, 0, 0.1)"
            style={{}}
          />
          <Text style={styles.progressText}>{Math.round(item.progress || 0)}%</Text>
        </View>
      )}

      {item.status !== 'valid' && item.progress >= 100 && (
        <View style={styles.statusContainer}>
          <Text
            style={[
              styles.mapStatus,
              {
                color: Colors.RED
              }
            ]}
          >
            {isPremium ? 'Update Required' : 'Premium Required'}
          </Text>

          {isPremium && (
            <View style={styles.actionsContainer}>
              <TouchableOpacity
                onPress={() => handleUpdate(item)}
                style={[styles.actionButton, styles.updateButton]}
                disabled={!isPremium}
              >
                <Text style={styles.actionButtonText}>Update</Text>
              </TouchableOpacity>
            </View>
          )}
        </View>
      )}
    </View>
  );

  return (
    <PageWrapper>
      <Header label="Offline Maps" />
      <ScrollView contentContainerStyle={{ gap: 12 }} showsVerticalScrollIndicator={false}>
        {/* <TouchableOpacity
          style={styles.button}
          onPress={() => {
            if (isPremium) {
              navigation.navigate(NAVIGATION_PAGES.OFFLINE_SELECT_MAP);
            } else {
              Alert.alert(
                'Premium Feature',
                'Offline maps are available only with premium subscription.',
                [{ text: 'OK' }]
              );
            }
          }}
        >
          <Text style={styles.buttonText}>Download New Map</Text>
        </TouchableOpacity> */}

        <TouchableOpacity
          style={styles.button}
          onPress={() => {
            if (isPremium) {
              navigation.navigate(NAVIGATION_PAGES.OFFLINE_SELECT_REGIONS);
            } else {
              setModalState({
                visible: true,
                type: 'success',
                action: () => {},
                message:
                  'This feature is available to Premium users. Premium account settings can be managed on our website.',
                title: 'Premium Feature'
              });
            }
          }}
        >
          <Text style={styles.buttonText}>Select regions</Text>
        </TouchableOpacity>

        {hasDownloadingMaps() && (
          <View style={styles.downloadingNoticeContainer}>
            <Text style={styles.downloadingNoticeText}>
              Offline map downloading requires the app to stay open and active. Downloads will pause
              if you leave the app or lock your screen.
            </Text>
          </View>
        )}

        {loading ? (
          <View style={styles.loadingContainer}>
            <Loading />
          </View>
        ) : maps.length === 0 ? (
          <View style={styles.emptyContainer}>
            <Text style={styles.emptyText}>No offline maps yet</Text>
            <Text style={styles.emptySubText}>Download maps to use them when you're offline</Text>
          </View>
        ) : (
          <FlatList
            data={maps}
            renderItem={renderItem}
            keyExtractor={(item) => item.id}
            contentContainerStyle={styles.listContainer}
            scrollEnabled={false}
          />
        )}
      </ScrollView>

      <WarningModal
        type={modalState.type}
        isVisible={modalState.visible}
        message={modalState.message}
        title={modalState.title}
        action={modalState.action}
        onClose={() => closeModal()}
      />
    </PageWrapper>
  );
}

const styles = StyleSheet.create({
  downloadingNoticeContainer: {
    backgroundColor: Colors.FILL_LIGHT,
    borderRadius: 8,
    paddingHorizontal: 12,
    paddingVertical: 8,
    alignItems: 'center',
    gap: 8
  },
  downloadingNoticeText: {
    fontSize: getFontSize(12),
    color: Colors.TEXT_GRAY,
    flex: 1
  },
  container: {
    flex: 1,
    backgroundColor: '#fff',
    paddingTop: 50
  },
  header: {
    flexDirection: 'row',
    justifyContent: 'space-between',
    alignItems: 'center',
    padding: 16,
    borderBottomWidth: 1,
    borderBottomColor: '#eee'
  },
  title: {
    fontSize: 20,
    fontWeight: 'bold'
  },
  addButton: {
    backgroundColor: '#0F67FE',
    paddingHorizontal: 12,
    paddingVertical: 8,
    borderRadius: 4
  },
  addButtonText: {
    color: '#fff',
    fontWeight: '500'
  },
  listContainer: {
    paddingBottom: 16,
    paddingTop: 8
  },
  mapItem: {
    backgroundColor: Colors.FILL_LIGHT,
    borderRadius: 8,
    paddingHorizontal: 16,
    paddingVertical: 12,
    marginBottom: 12,
    gap: 4
  },
  mapInfoContainer: {
    flexDirection: 'row',
    alignItems: 'center'
  },
  mapName: {
    fontSize: getFontSize(14),
    fontWeight: '600',
    color: Colors.DARK_BLUE,
    flex: 1
  },
  mapDetails: {
    fontSize: getFontSize(12),
    color: Colors.TEXT_GRAY
  },
  statusContainer: {
    marginTop: 12,
    flexDirection: 'row',
    justifyContent: 'space-between',
    alignItems: 'center'
  },
  mapStatus: {
    fontSize: 14,
    fontWeight: '500'
  },
  actionsContainer: {
    flexDirection: 'row'
  },
  actionButton: {
    paddingHorizontal: 12,
    paddingVertical: 6,
    borderRadius: 4,
    minWidth: 68,
    alignItems: 'center'
  },
  updateButton: {
    backgroundColor: Colors.ORANGE
  },
  deleteButton: {
    backgroundColor: Colors.RED
  },
  actionButtonText: {
    color: Colors.WHITE,
    fontSize: 12,
    fontWeight: '600'
  },
  emptyContainer: {
    flex: 1,
    justifyContent: 'center',
    alignItems: 'center',
    padding: 32
  },
  emptyText: {
    fontSize: 14,
    fontWeight: '600',
    marginTop: 16
  },
  emptySubText: {
    fontSize: 12,
    color: '#777',
    textAlign: 'center',
    marginTop: 8
  },
  loadingContainer: {
    flex: 1,
    justifyContent: 'center',
    alignItems: 'center'
  },
  editNameContainer: {
    flexDirection: 'row',
    alignItems: 'center'
  },
  iconButton: {
    padding: 8
  },
  downloadProgressContainer: {
    marginTop: 8,
    flexDirection: 'row',
    alignItems: 'center',
    justifyContent: 'space-between',
    gap: 4
  },
  progressText: {
    fontSize: 12,
    color: Colors.TEXT_GRAY,
    textAlign: 'right'
  },
  button: {
    display: 'flex',
    flexDirection: 'row',
    justifyContent: 'center',
    alignItems: 'center',
    borderRadius: 4,
    gap: 10,
    padding: 10,
    borderColor: Colors.DARK_BLUE,
    borderWidth: 1,
    borderStyle: 'solid'
  },
  buttonText: {
    color: Colors.DARK_BLUE,
    fontSize: getFontSize(14),
    fontFamily: 'redhat-700'
  }
});
