import { mdiChartTimelineVariant } from '@mdi/js';
import axios from 'axios';
import Head from 'next/head';
import { useRouter } from 'next/router';
import React, { ReactElement, useEffect, useState } from 'react';
import { toast, ToastContainer } from 'react-toastify';
import BaseButton from '../../components/BaseButton';
import CardBox from '../../components/CardBox';
import LayoutAuthenticated from '../../layouts/Authenticated';
import SectionMain from '../../components/SectionMain';
import SectionTitleLineWithButton from '../../components/SectionTitleLineWithButton';
import { getPageTitle } from '../../config';
import { useAppDispatch, useAppSelector } from '../../stores/hooks';
import {
  fetch as fetchProjects,
  create as createProject,
} from '../../stores/projects/projectsSlice';
import type { Project } from '../../types/entities';
import { logger } from '../../lib/logger';

const ProjectsListPage = () => {
  const router = useRouter();
  const dispatch = useAppDispatch();

  const projectsRaw = useAppSelector((state) => state.projects.projects) as
    | Project[]
    | Project
    | undefined;
  // Handle both array (from list fetch) and single object (after edit fetch)
  const projects: Project[] = Array.isArray(projectsRaw)
    ? projectsRaw
    : projectsRaw
      ? [projectsRaw]
      : [];
  const isLoading = useAppSelector((state) => state.projects.loading);

  const [isCreating, setIsCreating] = useState(false);
  const [isCloning, setIsCloning] = useState(false);
  const [isCloneOpen, setIsCloneOpen] = useState(false);
  const [cloneSourceId, setCloneSourceId] = useState('');

  useEffect(() => {
    dispatch(
      fetchProjects({ query: '?limit=100&page=0&sort=desc&field=updatedAt' }),
    );
  }, [dispatch]);

  useEffect(() => {
    if (projects.length > 0 && !cloneSourceId) {
      setCloneSourceId(projects[0].id);
    }
  }, [projects, cloneSourceId]);

  const buildNewProjectDraft = (): Partial<Project> => {
    const stamp = Date.now();
    return {
      name: `New Project ${new Date(stamp).toISOString().slice(0, 16).replace('T', ' ')}`,
      slug: `project-${stamp}`,
      description: '',
    };
  };

  const handleOpenProjectAssets = async (projectId: string) => {
    await router.push(`/projects/${projectId}`);
  };

  const handleCreateNewProject = async () => {
    setIsCreating(true);
    try {
      const result = await dispatch(
        createProject(buildNewProjectDraft()),
      ).unwrap();
      const createdId = result?.id;

      if (!createdId) {
        throw new Error('Project was created but id is missing in response');
      }

      await router.push(`/projects/${createdId}`);
    } catch (error: unknown) {
      const errorMessage =
        error instanceof Error ? error.message : 'Unknown error';
      logger.error(
        'Failed to create project:',
        error instanceof Error ? error : { error: errorMessage },
      );
      toast('Failed to create project', {
        type: 'error',
        position: 'bottom-center',
      });
    } finally {
      setIsCreating(false);
    }
  };

  const handleCloneProject = async () => {
    if (!cloneSourceId) {
      toast('Select source project first', {
        type: 'warning',
        position: 'bottom-center',
      });
      return;
    }

    setIsCloning(true);
    try {
      const response = await axios.post(`/projects/${cloneSourceId}/clone`);
      const createdId = response?.data?.id;

      if (!createdId) {
        throw new Error('Cloned project id is missing in response');
      }

      await router.push(`/projects/${createdId}`);
    } catch (error: unknown) {
      const errorMessage =
        error instanceof Error ? error.message : 'Unknown error';
      logger.error(
        'Failed to clone project:',
        error instanceof Error ? error : { error: errorMessage },
      );
      toast('Failed to clone project', {
        type: 'error',
        position: 'bottom-center',
      });
    } finally {
      setIsCloning(false);
    }
  };

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

        <CardBox
          className='mb-6'
          cardBoxClassName='flex flex-wrap items-center gap-3'
        >
          <BaseButton
            color='info'
            label={isCreating ? 'Creating...' : 'New Project'}
            onClick={handleCreateNewProject}
            disabled={isCreating || isCloning}
          />
          <BaseButton
            color='lightDark'
            label='Clone Project'
            onClick={() => setIsCloneOpen((prev) => !prev)}
            disabled={isCreating || isCloning || projects.length === 0}
          />

          {isCloneOpen && (
            <div className='flex items-center gap-2 ml-0 md:ml-2 w-full md:w-auto'>
              <select
                className='w-full md:w-80 border border-gray-300 rounded px-2 py-2 bg-white dark:bg-dark-800'
                value={cloneSourceId}
                onChange={(event) => setCloneSourceId(event.target.value)}
                disabled={isCreating || isCloning || projects.length === 0}
              >
                {projects.map((project) => (
                  <option key={project.id} value={project.id}>
                    {project.name}
                  </option>
                ))}
              </select>
              <BaseButton
                color='success'
                label={isCloning ? 'Cloning...' : 'Create Clone'}
                onClick={handleCloneProject}
                disabled={isCreating || isCloning || !cloneSourceId}
              />
            </div>
          )}
        </CardBox>

        <div className='grid grid-cols-1 lg:grid-cols-2 2xl:grid-cols-3 gap-4'>
          {!isLoading &&
            projects.map((project) => (
              <button
                key={project.id}
                type='button'
                className='text-left'
                onClick={() => handleOpenProjectAssets(project.id)}
              >
                <CardBox className='h-full hover:shadow-md transition-shadow'>
                  <h3 className='text-lg font-semibold'>{project.name}</h3>
                  <p className='text-sm text-gray-500 mt-1'>
                    Slug: {project.slug}
                  </p>
                  {!!project.description && (
                    <p className='text-sm text-gray-600 mt-3 line-clamp-3'>
                      {project.description}
                    </p>
                  )}
                </CardBox>
              </button>
            ))}

          {!isLoading && projects.length === 0 && (
            <CardBox>
              <p>No projects found.</p>
            </CardBox>
          )}
        </div>
      </SectionMain>
      <ToastContainer />
    </>
  );
};

ProjectsListPage.getLayout = function getLayout(page: ReactElement) {
  return (
    <LayoutAuthenticated permission='READ_PROJECTS'>{page}</LayoutAuthenticated>
  );
};

export default ProjectsListPage;
