"use client"

import { useEffect, useState } from "react"
import { usePage } from "@inertiajs/react"
import classNames from "classnames"

import {
  X,
  CheckCircle,
  XCircle,
} from "lucide-react"

import styles from "./alert.module.scss"

/* ==========================================
   TYPES
========================================== */

interface FlashMessages {
  success?: string | string[]
  error?: string | string[]
  message?: string | string[]
  code?: string
}

type ValidationErrors = Record<
  string,
  string | string[]
>

interface AlertItem {
  id: number
  message: string
  type: "success" | "error" | string
}

/* ==========================================
   COMPONENT
========================================== */

const Alert = () => {
  const {
    flash = {},
    errors = {},
  } = usePage<{
    flash?: FlashMessages
    errors?: ValidationErrors
  }>().props

  const [alerts, setAlerts] =
    useState<AlertItem[]>([])

  const capitalizeFirstLetter = (
    str: string
  ): string => {
    if (
      !str ||
      typeof str !== "string"
    ) {
      return ""
    }

    return (
      str.charAt(0).toUpperCase() +
      str.slice(1)
    )
  }

  useEffect(() => {
    const newAlerts: AlertItem[] = []

    const normalize = (
      value?: string | string[]
    ): string[] =>
      Array.isArray(value)
        ? value
        : value
        ? [value]
        : []

    const pushAlerts = (
      messages: string[],
      type: string
    ) => {
      messages.forEach((message) => {
        newAlerts.push({
          id:
            Date.now() +
            Math.random(),
          message,
          type,
        })
      })
    }

    /* ==========================================
       FLASH MESSAGES
    ========================================== */

    if (flash.error) {
      pushAlerts(
        normalize(flash.error),
        "error"
      )
    }

    if (flash.success) {
      pushAlerts(
        normalize(flash.success),
        "success"
      )
    }

    if (
      flash.message &&
      flash.code
    ) {
      pushAlerts(
        normalize(flash.message),
        flash.code.toLowerCase()
      )
    }

    /* ==========================================
       VALIDATION ERRORS
    ========================================== */

    if (
      Object.keys(errors).length > 0
    ) {
      const firstError =
        Object.values(errors)[0]

      pushAlerts(
        normalize(firstError),
        "error"
      )
    }

    /* ==========================================
       ADD ALERTS
    ========================================== */

    if (newAlerts.length > 0) {
      setAlerts((prev) => [
        ...prev,
        ...newAlerts,
      ])

      newAlerts.forEach((alert) => {
        setTimeout(() => {
          setAlerts((prev) =>
            prev.filter(
              (item) =>
                item.id !== alert.id
            )
          )
        }, 7000)
      })
    }
  }, [flash, errors])

  /* ==========================================
     CLOSE ALERT
  ========================================== */

  const handleClose = (
    id: number
  ) => {
    setAlerts((prev) =>
      prev.filter(
        (alert) => alert.id !== id
      )
    )
  }

  if (alerts.length === 0) {
    return null
  }

  return (
    <div
      className={
        styles.toastContainer
      }
    >
      {alerts.map(
        ({
          id,
          type,
          message,
        }) => {
          const alertClass =
            classNames(
              styles.alert,
              styles[
                `alert--${type}`
              ]
            )

          const helperClass =
            styles[
              `alert--${type}--helper`
            ]

          return (
            <div
              key={id}
              className={alertClass}
            >
              <div
                className={
                  helperClass
                }
              >
                {type ===
                "error" ? (
                  <>
                    <XCircle
                      size={14}
                    />

                    <span>
                      Failed
                    </span>
                  </>
                ) : (
                  <>
                    <CheckCircle
                      size={14}
                    />

                    <span>
                      Success
                    </span>
                  </>
                )}
              </div>

              <span
                className={
                  styles.message
                }
              >
                {capitalizeFirstLetter(
                  message
                )}
              </span>

              <button
                type="button"
                onClick={() =>
                  handleClose(id)
                }
                className={
                  styles.closeBtn
                }
                aria-label="Close alert"
              >
                <X size={16} />
              </button>
            </div>
          )
        }
      )}
    </div>
  )
}

export default Alert