import { FC, useCallback, useEffect, useMemo, useState } from "react"
import {
  ActivityIndicator,
  Dimensions,
  RefreshControl,
  ScrollView,
  TextStyle,
  TouchableOpacity,
  View,
  ViewStyle,
} from "react-native"

import { Button } from "@/components/Button"
import { Dialog } from "@/components/Dialog"
import { Icon } from "@/components/Icon"
import { Screen } from "@/components/Screen"
import { Skeleton, SkeletonContainer } from "@/components/Skeleton"
import { Text } from "@/components/Text"
import { useAuth } from "@/context/AuthContext"
import { translate } from "@/i18n/translate"
import { AppStackScreenProps } from "@/navigators/navigationTypes"
import { authApi } from "@/services/api/authApi"
import type { Session } from "@/services/api/authTypes"
import { useAppTheme } from "@/theme/context"
import { $styles } from "@/theme/styles"
import type { ThemedStyle } from "@/theme/types"
import { s } from "@/utils/responsive"
import { useHeader } from "@/utils/useHeader"

export const SessionManagementScreen: FC<AppStackScreenProps<"SessionManagement">> =
  function SessionManagementScreen({ navigation }) {
    const { themed, theme } = useAppTheme()
    const { accessToken } = useAuth()

    // Session state
    const [sessions, setSessions] = useState<Session[]>([])
    const [isLoading, setIsLoading] = useState(false)
    const [isRefreshing, setIsRefreshing] = useState(false)
    const [revokingSessionId, setRevokingSessionId] = useState<string | null>(null)
    const [isRevokingAll, setIsRevokingAll] = useState(false)

    // Dialog state
    const [confirmDialogVisible, setConfirmDialogVisible] = useState(false)
    const [confirmAllDialogVisible, setConfirmAllDialogVisible] = useState(false)
    const [successDialogVisible, setSuccessDialogVisible] = useState(false)
    const [successMessage, setSuccessMessage] = useState("")
    const [pendingSessionId, setPendingSessionId] = useState<string | null>(null)

    useHeader(
      {
        title: translate("securityScreen:activeSessions"),
        leftIcon: "back",
        onLeftPress: () => navigation.goBack(),
      },
      [],
    )

    // Fetch sessions
    const fetchSessions = useCallback(
      async (showLoading = true) => {
        if (!accessToken) return

        if (showLoading) setIsLoading(true)
        try {
          const result = await authApi.getSessions(accessToken, { active: true })
          if (result.kind === "ok" && result.data.data?.sessions) {
            setSessions(result.data.data.sessions)
          }
        } catch (e) {
          if (__DEV__) console.error("Failed to fetch sessions:", e)
        } finally {
          setIsLoading(false)
          setIsRefreshing(false)
        }
      },
      [accessToken],
    )

    // Initial fetch
    useEffect(() => {
      fetchSessions()
    }, [fetchSessions])

    // Pull to refresh
    const onRefresh = useCallback(() => {
      setIsRefreshing(true)
      fetchSessions(false)
    }, [fetchSessions])

    // Show confirm dialog for single session
    const handleRevokeSession = useCallback(
      (sessionId: string) => {
        if (!accessToken) return
        setPendingSessionId(sessionId)
        setConfirmDialogVisible(true)
      },
      [accessToken],
    )

    // Actually revoke a single session
    const confirmRevokeSession = useCallback(async () => {
      if (!accessToken || !pendingSessionId) return

      setConfirmDialogVisible(false)
      setRevokingSessionId(pendingSessionId)

      try {
        const result = await authApi.revokeSession(accessToken, pendingSessionId)
        if (result.kind === "ok") {
          setSessions((prev) => prev.filter((s) => s.id !== pendingSessionId))
          setSuccessMessage(translate("securityScreen:sessionRevoked"))
          setSuccessDialogVisible(true)
        }
      } catch (e) {
        if (__DEV__) console.error("Failed to revoke session:", e)
      } finally {
        setRevokingSessionId(null)
        setPendingSessionId(null)
      }
    }, [accessToken, pendingSessionId])

    // Show confirm dialog for all other sessions
    const handleRevokeAllOther = useCallback(() => {
      if (!accessToken) return
      setConfirmAllDialogVisible(true)
    }, [accessToken])

    // Actually revoke all other sessions
    const confirmRevokeAllOther = useCallback(async () => {
      if (!accessToken) return

      setConfirmAllDialogVisible(false)
      setIsRevokingAll(true)

      try {
        const result = await authApi.revokeOtherSessions(accessToken)
        if (result.kind === "ok") {
          const revokedCount = result.data.data?.revokedCount || 0
          // Keep only current session
          setSessions((prev) => prev.filter((s) => s.isCurrent))
          if (revokedCount > 0) {
            setSuccessMessage(translate("securityScreen:sessionsRevoked", { count: revokedCount }))
            setSuccessDialogVisible(true)
          }
        }
      } catch (e) {
        if (__DEV__) console.error("Failed to revoke other sessions:", e)
      } finally {
        setIsRevokingAll(false)
      }
    }, [accessToken])

    // Get device icon based on device type
    const getDeviceIcon = (deviceType: string): "monitor" | "smartphone" | "tablet" => {
      switch (deviceType.toLowerCase()) {
        case "desktop":
          return "monitor"
        case "mobile":
          return "smartphone"
        case "tablet":
          return "tablet"
        default:
          return "monitor"
      }
    }

    // Format last active time
    const formatLastActive = (dateString: string): string => {
      const date = new Date(dateString)
      const now = new Date()
      const diffMs = now.getTime() - date.getTime()
      const diffMins = Math.floor(diffMs / 60000)
      const diffHours = Math.floor(diffMs / 3600000)
      const diffDays = Math.floor(diffMs / 86400000)

      if (diffMins < 1) return "Just now"
      if (diffMins < 60) return `${diffMins}m ago`
      if (diffHours < 24) return `${diffHours}h ago`
      if (diffDays < 7) return `${diffDays}d ago`
      return date.toLocaleDateString()
    }

    // Get other sessions (not current)
    const otherSessions = sessions.filter((s) => !s.isCurrent)
    const currentSession = sessions.find((s) => s.isCurrent)

    return (
      <Screen preset="fixed" safeAreaEdges={["bottom"]} contentContainerStyle={$styles.flex1}>
        <ScrollView
          contentContainerStyle={[$styles.container, themed($container)]}
          showsVerticalScrollIndicator={false}
          refreshControl={
            <RefreshControl
              refreshing={isRefreshing}
              onRefresh={onRefresh}
              tintColor={theme.colors.tint}
            />
          }
        >
          <Text
            size="xs"
            tx="securityScreen:activeSessionsDescription"
            style={themed($description)}
          />

          {isLoading ? (
            <SessionListSkeleton />
          ) : (
            <>
              {/* Current Session */}
              {currentSession && (
                <View style={[themed($sessionCard), themed($currentSessionCard)]}>
                  <View style={$sessionHeader}>
                    <View style={themed($deviceIconContainer)}>
                      <Icon
                        icon={getDeviceIcon(currentSession.deviceInfo.deviceType)}
                        size={20}
                        color={theme.colors.tint}
                      />
                    </View>
                    <View style={$sessionInfo}>
                      <View style={$sessionTitleRow}>
                        <Text preset="bold" size="sm">
                          {currentSession.deviceInfo.deviceName ||
                            `${currentSession.deviceInfo.os} - ${currentSession.deviceInfo.browser}`}
                        </Text>
                        <View style={themed($currentBadge)}>
                          <Text size="xxs" style={themed($currentBadgeText)}>
                            {translate("securityScreen:currentDevice")}
                          </Text>
                        </View>
                      </View>
                      <Text size="xs" style={themed($sessionDetail)}>
                        {currentSession.location?.city
                          ? `${currentSession.location.city} · ${currentSession.ipAddress}`
                          : currentSession.ipAddress}
                      </Text>
                      <Text size="xs" style={themed($sessionDetail)}>
                        {translate("securityScreen:lastActive")}:{" "}
                        {formatLastActive(currentSession.lastActiveAt)}
                      </Text>
                    </View>
                  </View>
                </View>
              )}

              {/* Other Sessions */}
              {otherSessions.length > 0
                ? otherSessions.map((session) => (
                    <View key={session.id} style={themed($sessionCard)}>
                      <View style={$sessionHeader}>
                        <View style={themed($deviceIconContainerDim)}>
                          <Icon
                            icon={getDeviceIcon(session.deviceInfo.deviceType)}
                            size={20}
                            color={theme.colors.textDim}
                          />
                        </View>
                        <View style={$sessionInfo}>
                          <Text preset="bold" size="sm">
                            {session.deviceInfo.deviceName ||
                              `${session.deviceInfo.os} - ${session.deviceInfo.browser}`}
                          </Text>
                          <Text size="xs" style={themed($sessionDetail)}>
                            {session.location?.city
                              ? `${session.location.city} · ${session.ipAddress}`
                              : session.ipAddress}
                          </Text>
                          <Text size="xs" style={themed($sessionDetail)}>
                            {translate("securityScreen:lastActive")}:{" "}
                            {formatLastActive(session.lastActiveAt)}
                          </Text>
                        </View>
                        <TouchableOpacity
                          onPress={() => handleRevokeSession(session.id)}
                          disabled={revokingSessionId === session.id}
                          style={themed($logoutButton)}
                        >
                          {revokingSessionId === session.id ? (
                            <ActivityIndicator size="small" color={theme.colors.error} />
                          ) : (
                            <Text size="xs" style={themed($logoutButtonText)}>
                              {translate("securityScreen:logoutDevice")}
                            </Text>
                          )}
                        </TouchableOpacity>
                      </View>
                    </View>
                  ))
                : !currentSession && (
                    <View style={themed($emptyState)}>
                      <Text
                        size="sm"
                        tx="securityScreen:noOtherSessions"
                        style={themed($emptyStateText)}
                      />
                    </View>
                  )}
            </>
          )}
        </ScrollView>

        {/* Fixed Bottom Button - Only show when there are other sessions */}
        {otherSessions.length > 0 && (
          <View style={themed($bottomContainer)}>
            <Button
              tx="securityScreen:logoutAllOther"
              preset="reversed"
              onPress={handleRevokeAllOther}
              disabled={isRevokingAll}
              loading={isRevokingAll}
            />
            <Text
              size="xxs"
              tx="securityScreen:logoutAllOtherDescription"
              style={themed($logoutAllDescription)}
            />
          </View>
        )}

        {/* Confirm Single Session Logout Dialog */}
        <Dialog
          visible={confirmDialogVisible}
          onClose={() => setConfirmDialogVisible(false)}
          preset="destructive"
          titleTx="securityScreen:confirmLogout"
          messageTx="securityScreen:confirmLogoutMessage"
          confirmTx="securityScreen:logoutDevice"
          onConfirm={confirmRevokeSession}
          onCancel={() => setConfirmDialogVisible(false)}
        />

        {/* Confirm All Sessions Logout Dialog */}
        <Dialog
          visible={confirmAllDialogVisible}
          onClose={() => setConfirmAllDialogVisible(false)}
          preset="destructive"
          titleTx="securityScreen:confirmLogout"
          messageTx="securityScreen:confirmLogoutAllMessage"
          confirmTx="securityScreen:logoutAllOther"
          onConfirm={confirmRevokeAllOther}
          onCancel={() => setConfirmAllDialogVisible(false)}
        />

        {/* Success Dialog */}
        <Dialog
          visible={successDialogVisible}
          onClose={() => setSuccessDialogVisible(false)}
          message={successMessage}
          onConfirm={() => setSuccessDialogVisible(false)}
        />
      </Screen>
    )
  }

const $container: ThemedStyle<ViewStyle> = ({ spacing }) => ({
  paddingTop: spacing.lg,
})

const $description: ThemedStyle<TextStyle> = ({ colors, spacing }) => ({
  color: colors.textDim,
  marginBottom: spacing.lg,
})

const $sessionCard: ThemedStyle<ViewStyle> = ({ colors, spacing }) => ({
  backgroundColor: colors.palette.neutral100,
  borderRadius: s(12),
  padding: spacing.md,
  marginBottom: spacing.md,
  borderWidth: 1,
  borderColor: colors.palette.neutral300,
})

const $currentSessionCard: ThemedStyle<ViewStyle> = ({ colors }) => ({
  borderColor: colors.tint,
  borderWidth: 1.5,
})

const $deviceIconContainer: ThemedStyle<ViewStyle> = ({ colors }) => ({
  width: s(40),
  height: s(40),
  borderRadius: s(20),
  backgroundColor: `${colors.tint}15`,
  justifyContent: "center",
  alignItems: "center",
})

const $deviceIconContainerDim: ThemedStyle<ViewStyle> = ({ colors }) => ({
  width: s(40),
  height: s(40),
  borderRadius: s(20),
  backgroundColor: colors.palette.neutral200,
  justifyContent: "center",
  alignItems: "center",
})

const $sessionHeader: ViewStyle = {
  flexDirection: "row",
  alignItems: "center",
}

const $sessionInfo: ViewStyle = {
  flex: 1,
  marginLeft: s(14),
}

const $sessionTitleRow: ViewStyle = {
  flexDirection: "row",
  alignItems: "center",
  flexWrap: "wrap",
  gap: s(8),
}

const $currentBadge: ThemedStyle<ViewStyle> = ({ colors }) => ({
  backgroundColor: colors.tint,
  paddingHorizontal: s(6),
  paddingVertical: s(2),
  borderRadius: s(4),
})

const $currentBadgeText: ThemedStyle<TextStyle> = ({ colors }) => ({
  color: colors.palette.neutral100,
  fontWeight: "600",
})

const $sessionDetail: ThemedStyle<TextStyle> = ({ colors }) => ({
  color: colors.textDim,
  marginTop: s(2),
})

const $logoutButton: ThemedStyle<ViewStyle> = ({ colors, spacing }) => ({
  paddingHorizontal: spacing.sm,
  paddingVertical: spacing.xs,
  borderRadius: s(4),
  borderWidth: 1,
  borderColor: colors.error,
})

const $logoutButtonText: ThemedStyle<TextStyle> = ({ colors }) => ({
  color: colors.error,
  fontWeight: "600",
})

const $bottomContainer: ThemedStyle<ViewStyle> = ({ spacing }) => ({
  paddingHorizontal: spacing.lg,
  paddingBottom: spacing.md,
})

const $logoutAllDescription: ThemedStyle<TextStyle> = ({ colors, spacing }) => ({
  color: colors.textDim,
  textAlign: "center",
  marginTop: spacing.xs,
})

const $emptyState: ThemedStyle<ViewStyle> = ({ spacing }) => ({
  padding: spacing.xl,
  alignItems: "center",
})

const $emptyStateText: ThemedStyle<TextStyle> = ({ colors }) => ({
  color: colors.textDim,
})

// Card height: padding (16*2) + icon (40) = 72, plus marginBottom (16) = 88
const SKELETON_CARD_HEIGHT = 88
// Header height + description + container padding approximation
const SKELETON_HEADER_OFFSET = 120

/**
 * Skeleton list that fills the screen with diagonal shimmer effect
 */
function SessionListSkeleton() {
  const { themed, theme } = useAppTheme()

  const skeletonCount = useMemo(() => {
    const screenHeight = Dimensions.get("window").height
    const availableHeight = screenHeight - SKELETON_HEADER_OFFSET
    return Math.ceil(availableHeight / SKELETON_CARD_HEIGHT)
  }, [])

  return (
    <SkeletonContainer>
      {Array.from({ length: skeletonCount }).map((_, index) => (
        <View key={index} style={themed($sessionCard)}>
          <View style={$sessionHeader}>
            {/* Device icon - 40x40 circle */}
            <Skeleton width={40} height={40} radius="round" />

            {/* Session info */}
            <View style={$sessionInfo}>
              {/* Device name - bold sm (16px) */}
              <Skeleton width="65%" height={16} radius={4} />

              {/* Location/IP - xs (14px), marginTop: 2 */}
              <Skeleton
                width="50%"
                height={14}
                radius={4}
                style={{ marginTop: theme.spacing.xxs }}
              />

              {/* Last active - xs (14px), marginTop: 2 */}
              <Skeleton
                width="45%"
                height={14}
                radius={4}
                style={{ marginTop: theme.spacing.xxs }}
              />
            </View>
          </View>
        </View>
      ))}
    </SkeletonContainer>
  )
}
