import { useDispatch, useSelector } from 'react-redux'
import { resourceDir, join } from '@tauri-apps/api/path'
import { convertFileSrc } from '@tauri-apps/api/core'
import { v4 as uuidv4 } from 'uuid'
import { cn } from '@/lib/utils'
import { bytesToMbps } from '@/utils/tools'
import { errorToast } from '@/components/GlobalToast'
import { toast } from '@/components/ui/use-toast'
import { commands } from '@/bindings'
import {
  // installService,
  // uninstallService,
  // startCore,
  // stopCore,
  enableProxy,
  disableProxy,
} from '@/store/serviceSlice'
import { WebSocketClient } from '@/utils/webSocketClient'
import { ServiceControlPanel } from '@/components/ServiceControlPanel'
import { useCoreConfig } from '@/hooks/useCoreConfig'

import LineChart from '@/pages/home/components/LineChart'
import Links from '@/pages/home/components/Links'

import UnionSvg from '@/assets/svg/home/union.svg?react'

import ArrowDownSvg from '@/assets/svg/home/arrow-down.svg?react'
import ArrowUpSvg from '@/assets/svg/home/arrow-up.svg?react'

import type { AppDispatch, RootState } from '@/store'

import './index.scss'

const AgentOpenBtn = () => {
  return (
    <div className="proxy-btn w-[220px] h-[54px] p-1.5 bg-emerald-700 rounded-[10px] justify-start items-center gap-2.5 inline-flex">
      <div className="w-[74px] h-[46px]  bg-emerald-200 rounded-[8.93px] justify-center items-center gap-2 inline-flex">
        <UnionSvg className="animate-fade-in-medium" />
        <UnionSvg className="animate-fade-in-strong" />
      </div>
      <div className=" justify-center items-center flex flex-1">
        <div className="text-white text-xl font-semibold leading-7 ">
          开启代理
        </div>
      </div>
    </div>
  )
}

const AgentCloseBtn = ({ className }: { className?: string }) => {
  return (
    <div
      className={cn(
        'proxy-btn w-[220px] h-[54px] p-1.5 bg-emerald-700 rounded-[10px] justify-end items-center gap-2.5 inline-flex',
        className,
      )}
    >
      <div className=" justify-center items-center flex flex-1">
        <div className="text-white text-xl font-semibold leading-7">
          关闭代理
        </div>
      </div>
      <div className="w-[74px] h-[46px]  bg-emerald-200 rounded-[8.93px] justify-center items-center gap-2 inline-flex">
        <UnionSvg className="animate-fade-in-medium transform rotate-180" />
        <UnionSvg className="animate-fade-in-strong transform rotate-180" />
      </div>
    </div>
  )
}

const AgentInBtn = ({
  className,
  isProxyEnabled,
}: { className?: string; isProxyEnabled: boolean }) => {
  let timer: NodeJS.Timeout | null = null
  let index = 0
  let [opacityList, setOpacityList] = useState([
    'opacity-100',
    'opacity-50',
    'opacity-25',
  ])
  // todo 后期使用gasp 或者 formwork 替代定时器
  useEffect(() => {
    timer = setInterval(() => {
      switch (index) {
        case 0:
          opacityList = ['opacity-50', 'opacity-100', 'opacity-50']
          break
        case 1:
          opacityList = ['opacity-25', 'opacity-50', 'opacity-100']
          break
        case 2:
          opacityList = ['opacity-100', 'opacity-50', 'opacity-25']
          break
        default:
      }
      index++
      setOpacityList(opacityList)
      if (index === 3) {
        index = 0
      }
    }, 300)
    return () => {
      timer && clearInterval(timer)
    }
  }, [])

  return (
    <div
      className={cn(
        'proxy-btn-loading w-[220px] h-[54px] p-1 bg-emerald-700 rounded-[10px] justify-start items-center gap-2.5 inline-flex',
        className,
      )}
    >
      <div className="w-full h-full p-[4.46px] bg-emerald-200 rounded-lg justify-center items-center gap-[4.46px] inline-flex">
        <div className="text-[#232b54] text-xl font-semibold  leading-7 mr-[10px]">
          {isProxyEnabled ? '关闭中' : '代理中'}
        </div>
        <UnionSvg className={cn(opacityList[0])} />
        <UnionSvg className={cn(opacityList[1])} />
        <UnionSvg className={cn(opacityList[2])} />
      </div>
    </div>
  )
}

function Home() {
  let trafficWs: WebSocketClient | null = null
  const dispatch = useDispatch<AppDispatch>()
  const { loadCoreConfig } = useCoreConfig()
  const [videoPath, setVideoPath] = useState<string>('')
  const { countries, exitCountries } = useSelector(
    (state: RootState) => state.nodesReducer,
  )
  const { circuits, fallbackCircuit } = useSelector(
    (state: RootState) => state.circuitReducer,
  )
  const { isProxyEnabled, isCoreRunning } = useSelector(
    (state: RootState) => state.serviceReducer,
  )
  const [isProxyLoading, setIsProxyLoading] = useState(false)
  const [traffic, setTraffic] = useState<{
    send_bytes: number
    recv_bytes: number
  }>({ recv_bytes: 0, send_bytes: 0 })

  const isCircuitReady = useMemo(() => {
    // 判断是否有有链路并且至少有一个能用
    const circuitReady = circuits.some((circuit) => circuit?.state !== 'failed')
    if (
      circuitReady ||
      (fallbackCircuit && fallbackCircuit?.state !== 'failed')
    ) {
      return true
    } else {
      return false
    }
  }, [circuits, fallbackCircuit])

  // 处理代理开关
  const handleProxyToggle = async (
    isProxyEnabled: boolean,
    isCircuitReady: boolean,
    isCoreRunning: boolean,
  ) => {
    try {
      // 如果核心未运行，先启动核心
      if (!isCoreRunning) {
        await commands.startCore()
      }
      // 这里要先轮询去判断是否启动成功，如果启动失败，则抛出异常
      let isGetNodesResult = await commands.getNodes()
      let count = 0
      while (isGetNodesResult.status !== 'ok') {
        isGetNodesResult = await commands.getNodes()
        count++
        // 如果50次都没有开启成功核心那么启动失败
        if (count > 50) {
          throw new Error('启动核心失败')
        }
      }
      // 如果代理未启用且链路未就绪，创建默认链路
      // if (!isProxyEnabled && !isCircuitReady) {
      //   await dispatch(
      //     createCircuit({
      //       uid: uuidv4(),
      //       name: '系统默认链路',
      //       inbound: countries[0],
      //       outbound: exitCountries[exitCountries.length - 1],
      //       multi_hop: 3,
      //       fallback: true,
      //       rule_path: null,
      //       is_prefix: false,
      //     }),
      //   ).unwrap()
      // }

      setIsProxyLoading(true)

      // 切换代理状态
      await dispatch(isProxyEnabled ? disableProxy() : enableProxy()).unwrap()
    } catch (error) {
      console.log(error, 'error')
      const errorMessage = isProxyEnabled
        ? '关闭代理失败!'
        : '开启代理失败，请检查节点配置、或重新尝试开启'
      errorToast(errorMessage, toast)
      console.error('Proxy toggle failed:', error)
    } finally {
      setIsProxyLoading(false)
    }
  }

  const openWsTraffic = async () => {
    if (trafficWs) return
    const { api_port } = await loadCoreConfig()
    // todo! 后面会把二级制文件启动的参数作为配置项，这里暂时写死
    trafficWs = new WebSocketClient(`ws://127.0.0.1:${api_port}/traffic`, {
      headers: {
        Authorization: 'Bearer secret',
      },
    })

    // 执行 WebSocket 操作
    await trafficWs.connect()
    trafficWs.addListener((msg) => {
      if (msg.type === 'Text') {
        const result = JSON.parse(msg.data)
        setTraffic({
          recv_bytes: bytesToMbps(result.data.recv_bytes),
          send_bytes: bytesToMbps(result.data.send_bytes),
        })
      }
    })
  }

  const closeWsTraffic = async () => {
    if (trafficWs) {
      await trafficWs.disconnect()
      trafficWs = null
    }
  }

  const getVideoPath = async () => {
    const resourceDirPath = await resourceDir()
    // tauri 读取视频和音频不能直接像前端那样import video from 'xxx.mp4' 需要用convertFileSrc并且开启相应的权限，不然打包出来的引用会非常卡媒体文件越大越卡
    // https://v2.tauri.app/zh-cn/reference/javascript/api/namespacecore/#convertfilesrc
    const filePath = await join(
      resourceDirPath,
      'assets/video/crystal-ball.mp4',
    )
    const assetUrl = convertFileSrc(filePath)
    setVideoPath(assetUrl)
  }

  useEffect(() => {
    getVideoPath()
  }, [])

  useEffect(() => {
    if (isProxyEnabled) {
      openWsTraffic()
    } else {
      closeWsTraffic()
    }
    return () => {
      closeWsTraffic()
    }
  }, [isProxyEnabled])

  return (
    <main className="home w-full h-[100%] flex flex-col">
      <div className="w-full h-[217.81px] py-8 relative flex flex-shrink-0 overflow-hidden">
        <video
          id="my-video"
          src={videoPath}
          className="absolute top-0 -right-40 w-full h-[309px] object-cover transform -translate-y-[80px] pointer-events-none"
          autoPlay
          loop
          muted
          preload="auto"
        ></video>
        {/* <video src={BgVideo} className='absolute top-0 right-0 w-full h-[309px] object-none transform -translate-y-[80px] translate-x-[0px]' autoPlay loop muted></video> */}
        <div className="my-gradient"></div>
        <div className="w-fit h-full flex">
          <div className="relative px-12 pr-6  z-10 cursor-default no-select">
            <div className="text-zinc-900 text-3xl font-semibold  leading-9">
              您好呀，欢迎使用匿名反溯源网络系统！
            </div>
            <div className="mt-[11px] text-zinc-900 text-lg font-light leading-relaxed">
              当前链路稳定整体稳定，服务器处于低负载
            </div>
            <div
              className="w-fit cursor-pointer mt-5 flex items-center gap-x-4"
              onClick={() =>
                handleProxyToggle(isProxyEnabled, isCircuitReady, isCoreRunning)
              }
            >
              {isProxyLoading ? (
                <div className="group relative">
                  <AgentInBtn
                    className="group-hover:hidden"
                    isProxyEnabled={isProxyEnabled}
                  />
                  <AgentCloseBtn className="hidden group-hover:flex" />
                </div>
              ) : isProxyEnabled ? (
                <AgentCloseBtn />
              ) : (
                <AgentOpenBtn />
              )}
            </div>
          </div>
          {isProxyEnabled && (
            <div className="relative z-10 flex flex-col gap-y-[16px]">
              <div className="h-[58.1px]  rounded-xl justify-center items-center gap-4 flex">
                <div>
                  <div className="text-zinc-900 text-3xl font-semibold leading-9">
                    {traffic.send_bytes === 0
                      ? '0.000'
                      : traffic.send_bytes.toFixed(3)}
                  </div>
                  <div className="mt-2 flex items-center gap-1 text-zinc-600 text-sm font-normal leading-tight">
                    <ArrowDownSvg /> <span>下载/Mbps</span>
                  </div>
                </div>
                <LineChart data={traffic.send_bytes} lineColor="#2563eb" />
              </div>
              <div className="h-[58.1px]  rounded-xl justify-center items-center gap-4 flex">
                <div>
                  <div className="text-zinc-900 text-3xl font-semibold leading-9">
                    {traffic.recv_bytes === 0
                      ? '0.000'
                      : traffic.recv_bytes.toFixed(3)}
                  </div>

                  <div className="mt-2 flex items-center gap-1 text-zinc-600 text-sm font-normal leading-tight">
                    <ArrowUpSvg /> <span>上传/Mbps</span>
                  </div>
                </div>
                <LineChart data={traffic.recv_bytes} lineColor="#14b8a6" />
              </div>
            </div>
          )}
        </div>
      </div>
      <div className="flex flex-col flex-1 px-6 my-5">
        <Links
          isDefault={true}
          label="默认链路"
          className="h-[156px] flex-shrink-0"
        />
        <Links
          label="应用分流链路"
          className="mt-5 flex-1 flex flex-col"
          tableClassName="h-[100%]"
        />
      </div>
      {import.meta.env.DEV && <ServiceControlPanel />}
    </main>
  )
}

export default memo(Home)
