import { useContext, useEffect, useMemo, useState } from 'react'
import { Descriptions, Flex, Select, Space, Spin, Typography } from 'antd'
import { LoadingOutlined, SettingOutlined } from '@ant-design/icons'
import { useThemeContext } from '../context/ThemeContext'
import { ApiServerContext } from '../context/ApiServerContext'
import { ElectronContext } from '../context/ElectronContext'
import { AuthContext } from '../context/AuthContext'
import { useMessageContext } from '../context/MessageContext'
import useCollapseState from '../hooks/useCollapseState'
import InfoCollapse from '../common/InfoCollapse'
import ViewButton from '../common/ViewButton'
import EditButtons from '../common/EditButtons'

const { Text } = Typography
const { Option } = Select
const DEFAULT_UPDATE_BRANCH = 'main'

const Settings = () => {
  const { isDarkMode, isCompact, isSystem, setThemeMode, setDensityMode } =
    useThemeContext()
  const { fetchAppUpdateBranches } = useContext(ApiServerContext)
  const { isElectron, getAppSettings, setAppSettings } =
    useContext(ElectronContext)
  const { userProfile, setUserProfile } = useContext(AuthContext)
  const { showSuccess, showError } = useMessageContext()
  const [collapseState, updateCollapseState] = useCollapseState('Settings', {
    appearance: true,
    appUpdates: true
  })
  const [isEditing, setIsEditing] = useState(false)
  const [settingsLoading, setSettingsLoading] = useState(true)
  const [saving, setSaving] = useState(false)
  const [appSettings, setAppSettingsState] = useState({})
  const [draftSettings, setDraftSettings] = useState({})
  const [branches, setBranches] = useState([])
  const [branchLoading, setBranchLoading] = useState(false)

  useEffect(() => {
    const loadSettings = async () => {
      setSettingsLoading(true)
      const storedSettings = isElectron
        ? await getAppSettings()
        : userProfile?.settings || {}
      setAppSettingsState(storedSettings || {})
      setDraftSettings(storedSettings || {})
      setSettingsLoading(false)
    }

    loadSettings()
  }, [getAppSettings, isElectron, userProfile?.settings])

  useEffect(() => {
    if (settingsLoading || isEditing) return
    if (appSettings.theme) setThemeMode(appSettings.theme)
    if (appSettings.density) setDensityMode(appSettings.density)
  }, [
    appSettings.density,
    appSettings.theme,
    isEditing,
    setDensityMode,
    setThemeMode,
    settingsLoading
  ])

  useEffect(() => {
    if (!isElectron) {
      setBranches([])
      setBranchLoading(false)
      return
    }

    const loadBranches = async () => {
      setBranchLoading(true)
      const availableBranches = await fetchAppUpdateBranches()
      setBranches(availableBranches)

      setDraftSettings((previous) => {
        if (previous.appUpdateBranch) return previous

        const defaultBranch = availableBranches.includes(DEFAULT_UPDATE_BRANCH)
          ? DEFAULT_UPDATE_BRANCH
          : availableBranches[0]

        return defaultBranch
          ? { ...previous, appUpdateBranch: defaultBranch }
          : previous
      })

      setBranchLoading(false)
    }

    loadBranches()
  }, [fetchAppUpdateBranches, isElectron])

  const branchOptions = useMemo(
    () =>
      branches.map((branch) => (
        <Option key={branch} value={branch}>
          {branch}
        </Option>
      )),
    [branches]
  )
  const viewItems = [
    { key: 'appearance', label: 'Appearance Settings' },
    ...(isElectron ? [{ key: 'appUpdates', label: 'App Update Settings' }] : [])
  ]

  const getCurrentThemeValue = () => {
    if (isSystem) return 'system'
    return isDarkMode ? 'dark' : 'light'
  }

  const currentThemeValue = getCurrentThemeValue()
  const currentDensityValue = isCompact ? 'compact' : 'comfortable'
  const currentBranch =
    appSettings.appUpdateBranch ||
    (branches.includes(DEFAULT_UPDATE_BRANCH) ? DEFAULT_UPDATE_BRANCH : null) ||
    branches[0] ||
    'Not configured'

  const startEditing = () => {
    setDraftSettings({
      ...appSettings,
      appUpdateBranch:
        currentBranch === 'Not configured' ? undefined : currentBranch,
      theme: currentThemeValue,
      density: currentDensityValue
    })
    setIsEditing(true)
  }

  const cancelEditing = () => {
    setDraftSettings(appSettings)
    setIsEditing(false)
  }

  const handleSave = async () => {
    setSaving(true)

    try {
      const nextSettings = {
        ...appSettings,
        theme: draftSettings.theme,
        density: draftSettings.density,
        ...(isElectron
          ? { appUpdateBranch: draftSettings.appUpdateBranch }
          : {})
      }
      const saved = isElectron
        ? await setAppSettings(nextSettings)
        : Boolean(userProfile)

      if (!saved) {
        showError('Unable to save settings.')
        return
      }

      if (!isElectron) {
        setUserProfile((previous) => ({
          ...previous,
          settings: {
            ...(previous?.settings || {}),
            theme: draftSettings.theme,
            density: draftSettings.density
          }
        }))
      }

      setThemeMode(draftSettings.theme)
      setDensityMode(draftSettings.density)
      setAppSettingsState(nextSettings)
      setDraftSettings(nextSettings)
      setIsEditing(false)
      showSuccess('Settings saved.')
    } finally {
      setSaving(false)
    }
  }

  return (
    <Flex vertical gap='large' style={{ height: '100%', minHeight: 0 }}>
      <Flex justify='space-between' align='center'>
        <Space size='small'>
          <ViewButton
            disabled={settingsLoading}
            items={viewItems}
            visibleState={collapseState}
            updateVisibleState={updateCollapseState}
          />
        </Space>
        <EditButtons
          isEditing={isEditing}
          handleUpdate={handleSave}
          cancelEditing={cancelEditing}
          startEditing={startEditing}
          formValid={
            Boolean(draftSettings.theme && draftSettings.density) &&
            (!isElectron || Boolean(draftSettings.appUpdateBranch))
          }
          disabled={settingsLoading || (!isElectron && !userProfile)}
          loading={saving}
        />
      </Flex>
      <div style={{ height: '100%', minHeight: 0, overflowY: 'auto' }}>
        <Spin spinning={settingsLoading} indicator={<LoadingOutlined />}>
          <Flex vertical gap='large'>
            <InfoCollapse
              title='Appearance Settings'
              icon={<SettingOutlined />}
              active={collapseState.appearance}
              onToggle={(expanded) =>
                updateCollapseState('appearance', expanded)
              }
              collapseKey='appearance'
            >
              <Descriptions
                bordered
                column={{
                  xs: 1,
                  sm: 1,
                  md: 1,
                  lg: 2,
                  xl: 2,
                  xxl: 2
                }}
              >
                <Descriptions.Item label='Theme'>
                  {isEditing ? (
                    <Select
                      value={draftSettings.theme}
                      onChange={(value) =>
                        setDraftSettings((previous) => ({
                          ...previous,
                          theme: value
                        }))
                      }
                      style={{ width: '100%' }}
                    >
                      <Option value='light'>Light</Option>
                      <Option value='dark'>Dark</Option>
                      <Option value='system'>System</Option>
                    </Select>
                  ) : (
                    <Text>{currentThemeValue}</Text>
                  )}
                </Descriptions.Item>
                <Descriptions.Item label='UI Density'>
                  {isEditing ? (
                    <Select
                      value={draftSettings.density}
                      onChange={(value) =>
                        setDraftSettings((previous) => ({
                          ...previous,
                          density: value
                        }))
                      }
                      style={{ width: '100%' }}
                    >
                      <Option value='comfortable'>Comfortable</Option>
                      <Option value='compact'>Compact</Option>
                    </Select>
                  ) : (
                    <Text>{isCompact ? 'Compact' : 'Comfortable'}</Text>
                  )}
                </Descriptions.Item>
              </Descriptions>
            </InfoCollapse>
            {isElectron && (
              <InfoCollapse
                title='App Update Settings'
                icon={<SettingOutlined />}
                active={collapseState.appUpdates}
                onToggle={(expanded) =>
                  updateCollapseState('appUpdates', expanded)
                }
                collapseKey='appUpdates'
              >
                <Descriptions bordered column={1}>
                  <Descriptions.Item label='Branch'>
                    {isEditing ? (
                      <Select
                        value={draftSettings.appUpdateBranch}
                        onChange={(value) =>
                          setDraftSettings((previous) => ({
                            ...previous,
                            appUpdateBranch: value
                          }))
                        }
                        style={{ width: '100%' }}
                        loading={branchLoading}
                        placeholder='Select a branch'
                      >
                        {branchOptions}
                      </Select>
                    ) : (
                      <Text>{currentBranch}</Text>
                    )}
                  </Descriptions.Item>
                </Descriptions>
              </InfoCollapse>
            )}
          </Flex>
        </Spin>
      </div>
    </Flex>
  )
}

export default Settings
