import { Component, CUSTOM_ELEMENTS_SCHEMA, inject, OnInit, OnDestroy } from '@angular/core';
import { IProject } from '../models/project.model';
import { CommonModule } from '@angular/common';
import { MatDialog, MatDialogModule } from '@angular/material/dialog';
import { DynamicPopupComponent } from '../../shared/dynamic-popup/dynamic-popup';
import { DynamicFormConfig } from '../../shared/dynamic-form/dynamic-form-config';
import { ProjectDetailPopupComponent } from './project-detail-popup/project-detail-popup';
import { ConfirmDialogComponent } from '../../shared/confirm-dialog/confirm-dialog';
import { AdminQuery } from '../state/admin.query';
import { AdminStateService } from '../state/admin-state.service';
import { AdminService } from '../services/admin.service';
import { Subject, takeUntil, filter } from 'rxjs';
import { environment } from '../../../environments/environment';
import { HttpClient } from '@angular/common/http';

@Component({
  selector: 'app-projects',
  templateUrl: './projects.html',
  styleUrl: './projects.scss',
  imports: [CommonModule, MatDialogModule],
  schemas: [CUSTOM_ELEMENTS_SCHEMA]
})
export class Projects implements OnInit, OnDestroy {
  filter = 'All';
  projects: IProject[] = [];
  projectsCategories: string[] = [];
  categoryClicked = false;
  imagesOrigin = environment.apiUrl + '/images/';

  private dialog = inject(MatDialog);
  private http = inject(HttpClient);
  private adminQuery = inject(AdminQuery);
  private adminState = inject(AdminStateService);
  private adminService = inject(AdminService);
  private destroy$ = new Subject<void>();

  projects$ = this.adminQuery.projects$;
  loading$ = this.adminQuery.projectsLoading$;

  ngOnInit(): void {
    this.projects$
      .pipe(
        filter(data => data != null),
        takeUntil(this.destroy$)
      )
      .subscribe(data => {
        this.projects = data.projects;
        this.projectsCategories = data.projectsCategories;
      });

    // Only fetch if not already in store
    if (!this.adminQuery.getProjects()) {
      this.adminState.loadProjects()
        .pipe(takeUntil(this.destroy$))
        .subscribe();
    }
  }

  filterProjects(category: string) {
    this.filter = category;
    const allProjects = this.adminQuery.getProjects();
    if (!allProjects) return;

    this.projects = category === 'All'
      ? allProjects.projects
      : allProjects.projects.filter(
          (project: IProject) => project.categories.includes(category)
        );
  }

  private getProjectFormConfig(title: string): DynamicFormConfig {
    return {
      title,
      submitLabel: 'Save',
      fields: [
        { name: 'projectId', label: 'ID', type: 'hidden' },
        { name: 'name', label: 'Project Name', type: 'text', required: true },
        { name: 'description', label: 'Description', type: 'textarea' },
        { name: 'status', label: 'Status', type: 'text', placeholder: 'e.g. Completed, In Progress' },
        { name: 'categories', label: 'Categories', type: 'text', placeholder: 'Comma separated' },
        { name: 'roles', label: 'Roles', type: 'text', placeholder: 'Comma separated' },
        { name: 'responsibilities', label: 'Responsibilities', type: 'text', placeholder: 'Comma separated' },
        { name: 'technologiesUsed', label: 'Technologies Used', type: 'text', placeholder: 'Comma separated' },
        { name: 'startDate', label: 'Start Date', type: 'date' },
        { name: 'endDate', label: 'End Date', type: 'date' },
        { name: 'challenges', label: 'Challenges', type: 'textarea' },
        { name: 'lessonsLearned', label: 'Lessons Learned', type: 'textarea' },
        { name: 'impact', label: 'Impact', type: 'textarea' }
      ]
    };
  }

  private projectToFormData(project: IProject): Record<string, unknown> {
    return {
      ...project,
      categories: (project.categories ?? []).join(', '),
      roles: (project.roles ?? []).join(', '),
      responsibilities: (project.responsibilities ?? []).join(', '),
      technologiesUsed: (project.technologiesUsed ?? []).join(', ')
    };
  }

  private formDataToProject(formVal: Record<string, unknown>): IProject {
    const toArray = (val: unknown): string[] => {
      if (!val || typeof val !== 'string') return [];
      return val.split(',').map(s => s.trim()).filter(s => s.length > 0);
    };
    return {
      ...formVal,
      categories: toArray(formVal['categories']),
      roles: toArray(formVal['roles']),
      responsibilities: toArray(formVal['responsibilities']),
      technologiesUsed: toArray(formVal['technologiesUsed'])
    } as IProject;
  }

  private saveProject(project: IProject, isNew: boolean): void {
    const url = `${environment.apiUrl}/api/v1/admin/UpsertProject`;

    this.http.post<IProject>(url, project)
      .pipe(takeUntil(this.destroy$))
      .subscribe((res: IProject) => {
        const allProjects = this.adminQuery.getProjects();
        let updatedList: IProject[];

        if (isNew) {
          updatedList = [...(allProjects?.projects ?? []), res];
        } else {
          updatedList = (allProjects?.projects ?? []).map(p =>
            p.projectId === res.projectId ? res : p
          );
        }

        const categories = [...new Set(updatedList.flatMap(p => p.categories ?? []))];
        this.adminState.updateProjects({
          projects: updatedList,
          projectsCategories: categories.length ? categories : allProjects?.projectsCategories ?? []
        });
        this.filter = 'All';
      });
  }

  openViewProject(project: IProject): void {
    this.dialog.open(ProjectDetailPopupComponent, {
      data: project,
      panelClass: 'dark-popup-panel',
      width: '520px',
      maxHeight: '85vh'
    });
  }

  openEditProject(project: IProject): void {
    const config = this.getProjectFormConfig('Edit Project');
    const data = this.projectToFormData(project);

    const ref = this.dialog.open(DynamicPopupComponent, {
      data: { config, data },
      panelClass: 'dark-popup-panel'
    });

    ref.afterClosed()
      .pipe(takeUntil(this.destroy$))
      .subscribe((res: Record<string, unknown> | null) => {
        if (!res) return;
        const updated = this.formDataToProject(res);
        this.saveProject(updated, false);
      });
  }

  openAddProject(): void {
    const config = this.getProjectFormConfig('Add Project');
    const data: Record<string, unknown> = { projectId: 0 };

    const ref = this.dialog.open(DynamicPopupComponent, {
      data: { config, data },
      panelClass: 'dark-popup-panel'
    });

    ref.afterClosed()
      .pipe(takeUntil(this.destroy$))
      .subscribe((res: Record<string, unknown> | null) => {
        if (!res) return;
        const newProject = this.formDataToProject(res);
        this.saveProject(newProject, true);
      });
  }

  deleteProject(project: IProject): void {
    const ref = this.dialog.open(ConfirmDialogComponent, {
      data: {
        title: 'Delete Project',
        message: `Are you sure you want to delete "${project.name}"? This action cannot be undone.`
      },
      panelClass: 'dark-popup-panel',
      width: '420px'
    });

    ref.afterClosed()
      .pipe(takeUntil(this.destroy$))
      .subscribe((confirmed: boolean) => {
        if (!confirmed) return;

        this.adminService.deleteProject(project.projectId)
          .pipe(takeUntil(this.destroy$))
          .subscribe(() => {
            const allProjects = this.adminQuery.getProjects();
            const updatedList = (allProjects?.projects ?? []).filter(p => p.projectId !== project.projectId);
            const categories = [...new Set(updatedList.flatMap(p => p.categories ?? []))];

            this.adminState.updateProjects({
              projects: updatedList,
              projectsCategories: categories.length ? categories : []
            });
            this.filter = 'All';
          });
      });
  }

  ngOnDestroy(): void {
    this.destroy$.next();
    this.destroy$.complete();
  }
}
