import * as icon from '@mdi/js'
import Head from 'next/head'
import React from 'react'
import axios from 'axios'
import type { ReactElement } from 'react'
import Link from 'next/link'
import LayoutAuthenticated from '../layouts/Authenticated'
import SectionMain from '../components/SectionMain'
import SectionTitleLineWithButton from '../components/SectionTitleLineWithButton'
import BaseIcon from '../components/BaseIcon'
import BaseButton from '../components/BaseButton'
import CardBox from '../components/CardBox'
import { getPageTitle } from '../config'

import { hasPermission } from '../helpers/userPermissions'
import { getBusinessMenuLabel } from '../helpers/businessPlanLabels'
import { getPortalLabel, isInternalAdmin } from '../helpers/portalRoles'
import { fetchWidgets } from '../stores/roles/rolesSlice'
import { WidgetCreator } from '../components/WidgetCreator/WidgetCreator'
import { SmartWidget } from '../components/SmartWidget/SmartWidget'

import { useAppDispatch, useAppSelector } from '../stores/hooks'

type EntityKey =
  | 'users'
  | 'roles'
  | 'permissions'
  | 'businesses'
  | 'customers'
  | 'transactions'
  | 'review_requests'
  | 'stripe_events'
  | 'email_delivery_logs'
  | 'cron_runs'

type CountValue = string | number | null

type CountState = Record<EntityKey, CountValue>

type DashboardCard = {
  key: EntityKey
  label: string
  description: string
  href: string
  iconPath: string
  permission: string
}

type DashboardAction = {
  label: string
  href: string
  permission?: string | string[]
}

type DashboardActionGroup = {
  title: string
  description: string
  actions: DashboardAction[]
}

const loadingMessage = 'Loading...'

const entityKeys: EntityKey[] = [
  'users',
  'roles',
  'permissions',
  'businesses',
  'customers',
  'transactions',
  'review_requests',
  'stripe_events',
  'email_delivery_logs',
  'cron_runs',
]

const entityConfig: Record<EntityKey, { endpoint: string; permission: string }> = {
  users: { endpoint: 'users', permission: 'READ_USERS' },
  roles: { endpoint: 'roles', permission: 'READ_ROLES' },
  permissions: { endpoint: 'permissions', permission: 'READ_PERMISSIONS' },
  businesses: { endpoint: 'businesses', permission: 'READ_BUSINESSES' },
  customers: { endpoint: 'customers', permission: 'READ_CUSTOMERS' },
  transactions: { endpoint: 'transactions', permission: 'READ_TRANSACTIONS' },
  review_requests: { endpoint: 'review_requests', permission: 'READ_REVIEW_REQUESTS' },
  stripe_events: { endpoint: 'stripe_events', permission: 'READ_STRIPE_EVENTS' },
  email_delivery_logs: { endpoint: 'email_delivery_logs', permission: 'READ_EMAIL_DELIVERY_LOGS' },
  cron_runs: { endpoint: 'cron_runs', permission: 'READ_CRON_RUNS' },
}

const initialCounts = entityKeys.reduce((counts, key) => {
  counts[key] = loadingMessage

  return counts
}, {} as CountState)

const storeIcon =
  'mdiStore' in icon
    ? icon['mdiStore' as keyof typeof icon]
    : icon.mdiTable

const accountMultipleIcon =
  'mdiAccountMultiple' in icon
    ? icon['mdiAccountMultiple' as keyof typeof icon]
    : icon.mdiTable

const emailFastIcon =
  'mdiEmailFastOutline' in icon
    ? icon['mdiEmailFastOutline' as keyof typeof icon]
    : icon.mdiTable

const webhookIcon =
  'mdiWebhook' in icon
    ? icon['mdiWebhook' as keyof typeof icon]
    : icon.mdiTable

const emailCheckIcon =
  'mdiEmailCheckOutline' in icon
    ? icon['mdiEmailCheckOutline' as keyof typeof icon]
    : icon.mdiTable

const clockIcon =
  'mdiClockOutline' in icon
    ? icon['mdiClockOutline' as keyof typeof icon]
    : icon.mdiTable

function formatCount(value: CountValue) {
  if (value === null || value === undefined) return '—'
  if (typeof value === 'number') return value.toLocaleString()

  return value
}

function StatCard({
  card,
  value,
  corners,
  cardsStyle,
  iconsColor,
}: {
  card: DashboardCard
  value: CountValue
  corners: string
  cardsStyle: string
  iconsColor: string
}) {
  return (
    <Link href={card.href}>
      <div
        className={`${corners !== 'rounded-full' ? corners : 'rounded-3xl'} dark:bg-dark-900 ${cardsStyle} dark:border-dark-700 p-6 h-full hover:shadow-lg transition-shadow`}
      >
        <div className='flex justify-between gap-4'>
          <div>
            <div className='text-sm font-black uppercase tracking-[0.2em] text-gray-500 dark:text-gray-400'>
              {card.label}
            </div>
            <div className='mt-2 text-3xl leading-tight font-semibold'>
              {formatCount(value)}
            </div>
            <p className='mt-3 text-sm text-gray-500 dark:text-gray-400'>
              {card.description}
            </p>
          </div>
          <BaseIcon
            className={`${iconsColor} flex-none`}
            w='w-16'
            h='h-16'
            size={48}
            path={card.iconPath}
          />
        </div>
      </div>
    </Link>
  )
}

function ActionGroupCard({ group, currentUser }: { group: DashboardActionGroup; currentUser: any }) {
  const visibleActions = group.actions.filter(
    (action) => !action.permission || hasPermission(currentUser, action.permission),
  )

  if (!visibleActions.length) return null

  return (
    <CardBox className='h-full'>
      <div className='flex h-full flex-col'>
        <div>
          <h2 className='text-xl font-semibold'>{group.title}</h2>
          <p className='mt-2 text-sm text-gray-500 dark:text-gray-400'>{group.description}</p>
        </div>
        <div className='mt-6 grid gap-3'>
          {visibleActions.map((action) => (
            <BaseButton
              key={`${group.title}-${action.href}`}
              href={action.href}
              label={action.label}
              color='whiteDark'
              className='w-full justify-start'
            />
          ))}
        </div>
      </div>
    </CardBox>
  )
}

function PortalIntroCard({ currentUser, adminPortal }: { currentUser: any; adminPortal: boolean }) {
  const portalLabel = getPortalLabel(currentUser)
  const roleName = currentUser?.app_role?.name || 'User'
  const name = currentUser?.firstName || currentUser?.email || 'there'

  return (
    <CardBox className='mb-6 overflow-hidden'>
      <div className='grid gap-6 lg:grid-cols-[1.4fr_0.8fr] lg:items-center'>
        <div>
          <p className='text-xs font-black uppercase tracking-[0.25em] text-indigo-500 dark:text-indigo-300'>
            {portalLabel}
          </p>
          <h2 className='mt-3 text-2xl font-bold'>Welcome, {name}</h2>
          <p className='mt-3 text-gray-600 dark:text-gray-300'>
            {adminPortal
              ? 'This internal area is for running the SaaS business: customer accounts, business profiles, billing events, review operations, and access control.'
              : 'This customer workspace is for setting up your business profile, connecting review automation, managing customers, tracking transactions, and handling your subscription.'}
          </p>
        </div>
        <div className='rounded-3xl bg-slate-950 p-6 text-white'>
          <p className='text-sm text-slate-300'>Signed in as</p>
          <p className='mt-2 text-2xl font-bold'>{roleName}</p>
          <p className='mt-4 text-sm text-slate-300'>
            {adminPortal
              ? 'Customer workspace setup links are intentionally hidden from this portal.'
              : 'Internal platform administration links are intentionally hidden from this workspace.'}
          </p>
        </div>
      </div>
    </CardBox>
  )
}

const Dashboard = () => {
  const dispatch = useAppDispatch()
  const iconsColor = useAppSelector((state) => state.style.iconsColor)
  const corners = useAppSelector((state) => state.style.corners)
  const cardsStyle = useAppSelector((state) => state.style.cardsStyle)
  const { currentUser } = useAppSelector((state) => state.auth)
  const { isFetchingQuery } = useAppSelector((state) => state.openAi)
  const { rolesWidgets, loading } = useAppSelector((state) => state.roles)
  const [counts, setCounts] = React.useState<CountState>(initialCounts)
  const [widgetsRole, setWidgetsRole] = React.useState({
    role: { value: '', label: '' },
  })

  const adminPortal = isInternalAdmin(currentUser)
  const businessLabel = getBusinessMenuLabel(currentUser?.subscriptionPlanId)
  const businessProfilesLabel = adminPortal ? 'Business profiles' : businessLabel

  const loadData = React.useCallback(async () => {
    if (!currentUser) return

    const requests = entityKeys.map(async (key) => {
      const config = entityConfig[key]

      if (!hasPermission(currentUser, config.permission)) {
        return { key, count: null }
      }

      const response = await axios.get(`/${config.endpoint}/count`)

      return { key, count: response.data.count as CountValue }
    })

    const results = await Promise.allSettled(requests)

    setCounts((previousCounts) => {
      const nextCounts = { ...previousCounts }

      results.forEach((result, index) => {
        const key = entityKeys[index]

        if (result.status === 'fulfilled') {
          nextCounts[result.value.key] = result.value.count
        } else {
          console.error(`Failed to load ${key} dashboard count:`, result.reason)
          nextCounts[key] = 'Error'
        }
      })

      return nextCounts
    })
  }, [currentUser])

  const getWidgets = React.useCallback(async (roleId: string) => {
    await dispatch(fetchWidgets(roleId))
  }, [dispatch])

  React.useEffect(() => {
    if (!currentUser) return

    loadData().then()
    setWidgetsRole({
      role: {
        value: currentUser?.app_role?.id,
        label: currentUser?.app_role?.name,
      },
    })
  }, [currentUser, loadData])

  React.useEffect(() => {
    if (!currentUser || !widgetsRole?.role?.value || adminPortal) return

    getWidgets(widgetsRole?.role?.value || '').then()
  }, [adminPortal, currentUser, getWidgets, widgetsRole?.role?.value])

  const adminCards: DashboardCard[] = [
    {
      key: 'users',
      label: 'Customer accounts',
      description: 'Owners and team users across the platform.',
      href: '/users/users-list',
      iconPath: icon.mdiAccountGroup,
      permission: 'READ_USERS',
    },
    {
      key: 'businesses',
      label: 'Business profiles',
      description: 'Business locations connected to review flows.',
      href: '/businesses/businesses-list',
      iconPath: storeIcon,
      permission: 'READ_BUSINESSES',
    },
    {
      key: 'transactions',
      label: 'Transactions',
      description: 'Payment records feeding review requests.',
      href: '/transactions/transactions-list',
      iconPath: icon.mdiCreditCardOutline,
      permission: 'READ_TRANSACTIONS',
    },
    {
      key: 'review_requests',
      label: 'Review requests',
      description: 'Review invitations generated by the system.',
      href: '/review_requests/review_requests-list',
      iconPath: emailFastIcon,
      permission: 'READ_REVIEW_REQUESTS',
    },
    {
      key: 'stripe_events',
      label: 'Payment events',
      description: 'Stripe webhook events and processing status.',
      href: '/stripe_events/stripe_events-list',
      iconPath: webhookIcon,
      permission: 'READ_STRIPE_EVENTS',
    },
    {
      key: 'cron_runs',
      label: 'Automation runs',
      description: 'Scheduled background job execution history.',
      href: '/cron_runs/cron_runs-list',
      iconPath: clockIcon,
      permission: 'READ_CRON_RUNS',
    },
  ]

  const customerCards: DashboardCard[] = [
    {
      key: 'businesses',
      label: businessProfilesLabel,
      description: 'Your business profile and Google review destination.',
      href: '/businesses/businesses-list',
      iconPath: storeIcon,
      permission: 'READ_BUSINESSES',
    },
    {
      key: 'customers',
      label: 'Customers',
      description: 'Customer records created from payments or imports.',
      href: '/customers/customers-list',
      iconPath: accountMultipleIcon,
      permission: 'READ_CUSTOMERS',
    },
    {
      key: 'transactions',
      label: 'Transactions',
      description: 'Payments that can trigger review follow-up.',
      href: '/transactions/transactions-list',
      iconPath: icon.mdiCreditCardOutline,
      permission: 'READ_TRANSACTIONS',
    },
    {
      key: 'review_requests',
      label: 'Review requests',
      description: 'Messages scheduled or sent to customers.',
      href: '/review_requests/review_requests-list',
      iconPath: emailFastIcon,
      permission: 'READ_REVIEW_REQUESTS',
    },
    {
      key: 'email_delivery_logs',
      label: 'Email delivery',
      description: 'Delivery activity for review request emails.',
      href: '/email_delivery_logs/email_delivery_logs-list',
      iconPath: emailCheckIcon,
      permission: 'READ_EMAIL_DELIVERY_LOGS',
    },
  ]

  const adminActionGroups: DashboardActionGroup[] = [
    {
      title: 'Customer operations',
      description: 'Support customer accounts and the business profiles they manage.',
      actions: [
        { label: 'Review customer accounts', href: '/users/users-list', permission: 'READ_USERS' },
        { label: 'Review business profiles', href: '/businesses/businesses-list', permission: 'READ_BUSINESSES' },
        { label: 'Review end customers', href: '/customers/customers-list', permission: 'READ_CUSTOMERS' },
      ],
    },
    {
      title: 'Billing & review operations',
      description: 'Monitor payment data, webhook events, review requests, and delivery health.',
      actions: [
        { label: 'View transactions', href: '/transactions/transactions-list', permission: 'READ_TRANSACTIONS' },
        { label: 'View payment events', href: '/stripe_events/stripe_events-list', permission: 'READ_STRIPE_EVENTS' },
        { label: 'View review requests', href: '/review_requests/review_requests-list', permission: 'READ_REVIEW_REQUESTS' },
        { label: 'View email delivery logs', href: '/email_delivery_logs/email_delivery_logs-list', permission: 'READ_EMAIL_DELIVERY_LOGS' },
        { label: 'View automation runs', href: '/cron_runs/cron_runs-list', permission: 'READ_CRON_RUNS' },
      ],
    },
    {
      title: 'Platform access control',
      description: 'Manage internal roles and permissions for the platform.',
      actions: [
        { label: 'Manage roles', href: '/roles/roles-list', permission: 'READ_ROLES' },
        { label: 'Manage permissions', href: '/permissions/permissions-list', permission: 'READ_PERMISSIONS' },
      ],
    },
  ]

  const customerActionGroups: DashboardActionGroup[] = [
    {
      title: 'Review automation setup',
      description: 'Configure the business profile, review request templates, and payment triggers.',
      actions: [
        { label: 'Open Review Flow', href: '/reviewflow' },
        { label: `Manage ${businessLabel}`, href: '/businesses/businesses-list', permission: 'READ_BUSINESSES' },
        { label: 'Manage review requests', href: '/review_requests/review_requests-list', permission: 'READ_REVIEW_REQUESTS' },
      ],
    },
    {
      title: 'Customer records',
      description: 'Track customers and transactions that power follow-up messages.',
      actions: [
        { label: 'Manage customers', href: '/customers/customers-list', permission: 'READ_CUSTOMERS' },
        { label: 'View transactions', href: '/transactions/transactions-list', permission: 'READ_TRANSACTIONS' },
        { label: 'View email delivery', href: '/email_delivery_logs/email_delivery_logs-list', permission: 'READ_EMAIL_DELIVERY_LOGS' },
      ],
    },
    {
      title: 'Plan & billing',
      description: 'Review plan limits, usage, and billing status for this workspace.',
      actions: [
        { label: 'Open subscription', href: '/subscription' },
      ],
    },
  ]

  const cards = adminPortal ? adminCards : customerCards
  const actionGroups = adminPortal ? adminActionGroups : customerActionGroups
  const visibleCards = cards.filter((card) => hasPermission(currentUser, card.permission))
  const title = adminPortal ? 'Internal admin portal' : 'Customer workspace'
  const sectionIcon = adminPortal ? icon.mdiShieldAccountVariantOutline : icon.mdiChartTimelineVariant
  const showCustomerWidgets = !adminPortal && hasPermission(currentUser, 'CREATE_ROLES')

  return (
    <>
      <Head>
        <title>{getPageTitle(title)}</title>
      </Head>
      <SectionMain>
        <SectionTitleLineWithButton icon={sectionIcon} title={title} main>
          {''}
        </SectionTitleLineWithButton>

        <PortalIntroCard currentUser={currentUser} adminPortal={adminPortal} />

        {showCustomerWidgets && (
          <WidgetCreator
            currentUser={currentUser}
            isFetchingQuery={isFetchingQuery}
            setWidgetsRole={setWidgetsRole}
            widgetsRole={widgetsRole}
          />
        )}
        {!!rolesWidgets.length && showCustomerWidgets && (
          <p className='mb-4 text-gray-500 dark:text-gray-400'>
            {`${widgetsRole?.role?.label || 'Users'}'s widgets`}
          </p>
        )}

        {!adminPortal && (
          <div className='grid grid-cols-1 gap-6 lg:grid-cols-4 mb-6 grid-flow-dense'>
            {(isFetchingQuery || loading) && (
              <div className={`${corners !== 'rounded-full' ? corners : 'rounded-3xl'} dark:bg-dark-900 text-lg leading-tight text-gray-500 flex items-center ${cardsStyle} dark:border-dark-700 p-6`}>
                <BaseIcon
                  className={`${iconsColor} animate-spin mr-5`}
                  w='w-16'
                  h='h-16'
                  size={48}
                  path={icon.mdiLoading}
                />{' '}
                Loading widgets...
              </div>
            )}

            {rolesWidgets.map((widget) => (
              <SmartWidget
                key={widget.id}
                userId={currentUser?.id}
                widget={widget}
                roleId={widgetsRole?.role?.value || ''}
                admin={false}
              />
            ))}
          </div>
        )}

        {!adminPortal && !!rolesWidgets.length && <hr className='my-6' />}

        <div id='dashboard' className='grid grid-cols-1 gap-6 lg:grid-cols-3 mb-6'>
          {visibleCards.map((card) => (
            <StatCard
              key={`${card.key}-${card.label}`}
              card={card}
              value={counts[card.key]}
              corners={corners}
              cardsStyle={cardsStyle}
              iconsColor={iconsColor}
            />
          ))}
        </div>

        <div className='grid grid-cols-1 gap-6 lg:grid-cols-3'>
          {actionGroups.map((group) => (
            <ActionGroupCard key={group.title} group={group} currentUser={currentUser} />
          ))}
        </div>
      </SectionMain>
    </>
  )
}

Dashboard.getLayout = function getLayout(page: ReactElement) {
  return <LayoutAuthenticated>{page}</LayoutAuthenticated>
}

export default Dashboard
