import Container from '@/components/shared/Container'
import { Button, Checkbox, Dialog, Input, Menu, toast } from '@/components/ui'
import { useConfig } from '@/components/ui/ConfigProvider'
import Notification from '@/components/ui/Notification'
import {
  GetPermissionListResultDto,
  PermissionGrantInfoDto,
  PermissionGroupDto,
  PermissionWithGroupName,
  PermissionWithStyle,
  UpdatePermissionDto,
} from '@/proxy/admin/models'
import { getPermissions, updatePermissions } from '@/services/identity.service'
import { useStoreActions, useStoreState } from '@/store'
import { useLocalization } from '@/utils/hooks/useLocalization'
import { ChangeEvent, useEffect, useMemo, useState } from 'react'

function RolesPermission({
  open,
  onDialogClose,
  name,
}: {
  open: boolean
  onDialogClose: () => void
  name: string
}) {
  const providerName = 'R'
  const { translate } = useLocalization()
  const { getConfig } = useStoreActions((a) => a.abpConfig)

  const [isLoading, setIsLoading] = useState(false)
  const [permissionList, setPermissionList] = useState<GetPermissionListResultDto>()
  const [selectedGroup, setSelectedGroup] = useState<PermissionGroupDto | undefined>()
  const [selectedGroupPermissions, setSelectedGroupPermissions] = useState<PermissionWithStyle[]>(
    [],
  )
  const [searchTerm, setSearchTerm] = useState('')
  const mode = useStoreState((state) => state.theme.mode)
  const tenant = useStoreState((state) => state.auth.tenant)

  const { direction } = useConfig()
  const className = `m${direction[0]}-`

  const fetchDataPermissions = async () => {
    if (!name) return

    const response = await getPermissions(providerName, name)
    const data = response.data

    const tenantGroup = tenant?.menuGroup?.trim()
    if (!tenantGroup) {
      console.warn('Tenant menuGroup boş, tüm izinler gösterilecek')
      setPermissionList(data)
      return
    }

    const filteredGroups = data.groups
      .map((group: any) => {
        const filteredPermissions = group.permissions.filter(
          (perm: any) => Array.isArray(perm.menuGroup) && perm.menuGroup.includes(tenantGroup),
        )

        return { ...group, permissions: filteredPermissions }
      })
      .filter((group: any) => group.permissions.length > 0)

    const filteredData = { ...data, groups: filteredGroups }

    console.log('Filtered permissions by tenant group:', tenantGroup, filteredData)
    setPermissionList(filteredData)
  }

  const changeGroup = (groupName?: string) => {
    const group = permissionList?.groups.find((a: any) => a.name === groupName)

    if (!group) {
      setSelectedGroup(undefined)
      setSelectedGroupPermissions([])
      return
    }

    setSelectedGroup(group)

    const selectedGroupPerm = group.permissions.map(
      (permission: any) =>
        ({
          ...permission,
          class: className + findMargin(group.permissions, permission) * 4,
        }) as PermissionWithStyle,
    )

    setSelectedGroupPermissions(selectedGroupPerm)
  }

  const onDialogOk = async () => {
    setIsLoading(true)
    setTimeout(async () => {
      if (permissionList?.groups && name) {
        const listPermissions = await getPermissions(providerName, name)
        const unChangedPermissions = getPermissionsWithGroupName(listPermissions.data?.groups)
        const changedPermissions = getPermissionsWithGroupName(permissionList.groups)

        const updatePermList: UpdatePermissionDto[] = changedPermissions
          .filter((per) =>
            (unChangedPermissions.find((unChanged) => unChanged.name === per.name) || {})
              .isGranted === per.isGranted
              ? false
              : true,
          )
          .map(({ name, isGranted }) => ({ name, isGranted }))

        updatePermissions(providerName, name, { permissions: updatePermList })
        toast.push(<Notification title={'Permission updated'} type="success" />, {
          placement: 'top-end',
        })
      }

      onDialogClose()
      setIsLoading(false)
    }, 1000)

    setTimeout(async () => {
      getConfig(true)
    }, 6000)
  }

  function getPermissionsWithGroupName(groups: PermissionGroupDto[]): PermissionWithGroupName[] {
    return groups.reduce(
      (acc, val) => [
        ...acc,
        ...val.permissions.map<PermissionWithGroupName>((p: any) => ({
          ...p,
          groupName: val.name || '',
        })),
      ],
      [] as PermissionWithGroupName[],
    )
  }

  function findMargin(
    permissions: PermissionGrantInfoDto[],
    permission: PermissionGrantInfoDto,
    level = 0,
  ): number {
    const parentPermission = permissions.find((per) => per.name === permission.parentName)
    if (parentPermission) {
      return findMargin(permissions, parentPermission, level + 1)
    } else {
      return level
    }
  }

  const isAllSelected = useMemo(
    () =>
      permissionList?.groups.every((group: any) =>
        group.permissions.every((permission: any) => permission.isGranted),
      ),
    [permissionList],
  )

  const isAllSelectedForGroup = useMemo(
    () => selectedGroupPermissions.every((permission) => permission.isGranted),
    [selectedGroupPermissions],
  )

  const filteredPermissions = useMemo(() => {
    if (!searchTerm) {
      return selectedGroupPermissions
    }

    const lowerTerm = searchTerm.toLowerCase()

    // 1️⃣ Sadece 1. kırınımdakileri (parent olmayanları değil) ara
    const topLevelMatches = selectedGroupPermissions.filter(
      (p) =>
        !p.parentName && // parentName yoksa bu 1. kırınım demektir
        translate('::' + p.displayName)
          .toLowerCase()
          .includes(lowerTerm),
    )

    // 2️⃣ Her bulunan parent’ın altındaki child izinleri ekle
    const result: PermissionWithStyle[] = []
    topLevelMatches.forEach((parent) => {
      result.push(parent)

      // Alt kırılımları bul
      const children = selectedGroupPermissions.filter((child) => child.parentName === parent.name)
      result.push(...children)
    })

    return result
  }, [selectedGroupPermissions, searchTerm, translate])

  const onSelectAll = (value: boolean, e: ChangeEvent<HTMLInputElement>) => {
    if (!permissionList) {
      return
    }

    const currentGroupName = selectedGroup?.name
    setSelectedGroup(undefined)
    setSelectedGroupPermissions([])

    if (e.target.name === 'group') {
      permissionList?.groups
        .find((group: any) => group.name === selectedGroup?.name)
        ?.permissions.forEach((permission: any) => {
          permission.isGranted = value
        })
    } else {
      permissionList?.groups.forEach((group: any) => {
        group.permissions.forEach((permission: any) => {
          permission.isGranted = value
        })
      })
    }

    setPermissionList({ ...permissionList })

    changeGroup(currentGroupName)
  }

  function onClickCheckbox(clickedPermission: PermissionGrantInfoDto) {
    if (!permissionList) {
      return
    }

    const groupPerm = selectedGroupPermissions.map((per) => {
      if (clickedPermission.name === per.name) {
        return { ...per, isGranted: !per.isGranted }
      } else if (clickedPermission.name === per.parentName && clickedPermission.isGranted) {
        return { ...per, isGranted: false }
      } else if (clickedPermission.parentName === per.name && !clickedPermission.isGranted) {
        return { ...per, isGranted: true }
      }
      return per
    })

    const permGroup = permissionList?.groups.find((a: any) => a.name === selectedGroup?.name)
    if (permGroup) {
      permGroup.permissions = groupPerm
    }

    setPermissionList({ ...permissionList })
    setSelectedGroupPermissions(groupPerm)
  }

  useEffect(() => {
    fetchDataPermissions()
  }, [name])

  return permissionList ? (
    <Container>
      <Dialog
        width="60%"
        isOpen={open}
        onAfterOpen={() => changeGroup(permissionList?.groups[0].name)}
        onClose={onDialogClose}
        onRequestClose={onDialogClose}
      >
        <h5 className="mb-1">
          {translate('::Permission')} - {name}
        </h5>
        <hr className="mt-1 mb-2"></hr>

        <div className="flex flex-col md:flex-row gap-4 mb-1">
          <div style={{ width: '30%' }}>
            <Checkbox name="all" checked={isAllSelected} onChange={onSelectAll}>
              {translate('AbpPermissionManagement::SelectAllInAllTabs')}
            </Checkbox>
          </div>
          <div style={{ width: '70%' }}>
            <Checkbox name="group" checked={isAllSelectedForGroup} onChange={onSelectAll}>
              {translate('AbpPermissionManagement::SelectAllInThisTab')}
            </Checkbox>
          </div>
        </div>

        <div className="flex flex-col md:flex-row gap-4">
          <div style={{ width: '30%' }} className="max-h-[450px] overflow-y-auto">
            <hr className="mb-2"></hr>
            <Menu
              className="w-full"
              variant={mode}
              defaultActiveKeys={[selectedGroup?.displayName ?? '']}
            >
              {permissionList?.groups.map((group: any) => (
                <Menu.MenuItem
                  key={group.name}
                  className="break-all whitespace-normal"
                  eventKey={group.name}
                  onSelect={changeGroup}
                >
                  {translate('::' + group.displayName)} (
                  {group.permissions.filter((a: any) => a.isGranted).length})
                </Menu.MenuItem>
              ))}
            </Menu>
          </div>
          <div style={{ width: '70%' }} className="max-h-[450px] overflow-y-auto">
            <hr className="mb-2"></hr>
            <Input
              size="sm"
              className="mb-2"
              placeholder="Yetkiler içinde ara..."
              value={searchTerm}
              onChange={(e) => setSearchTerm(e.target.value)}
            />
            <div className="my-1">
              {filteredPermissions.map((permission) => (
                <div key={permission.name}>
                  <Checkbox
                    name={permission.name}
                    className={permission.class}
                    checked={permission.isGranted}
                    onChange={() => onClickCheckbox(permission)}
                  >
                    {translate('::' + permission.displayName)}
                  </Checkbox>
                </div>
              ))}
            </div>
          </div>
        </div>
        <div className="text-right mt-6">
          <Button className="ltr:mr-2 rtl:ml-2" variant="plain" onClick={onDialogClose}>
            {translate('::Cancel')}
          </Button>
          <Button variant="solid" loading={isLoading} onClick={onDialogOk}>
            {isLoading ? translate('::SavingWithThreeDot') : translate('::Save')}
          </Button>
        </div>
      </Dialog>
    </Container>
  ) : (
    <></>
  )
}

export default RolesPermission
