import fs from 'fs/promises';
import path from 'path';
import matter from 'gray-matter';
import type { Project, IdeaMotriz, Personaje, Capitulo, GuionConductor, Escaleta, CharacterAssetsData, EmotionVariant } from '@/types/project';

const PROJECTS_DIR = path.join(process.cwd(), 'projects');

// Asegurar que existe el directorio de proyectos
async function ensureProjectsDir() {
  try {
    await fs.access(PROJECTS_DIR);
  } catch {
    await fs.mkdir(PROJECTS_DIR, { recursive: true });
  }
}

// Crear slug desde nombre
function slugify(text: string): string {
  return text
    .toLowerCase()
    .normalize('NFD')
    .replace(/[\u0300-\u036f]/g, '')
    .replace(/[^a-z0-9]+/g, '-')
    .replace(/(^-|-$)/g, '');
}

// =====================
// PROYECTOS
// =====================

export async function listProjects(): Promise<Project[]> {
  await ensureProjectsDir();
  
  const dirs = await fs.readdir(PROJECTS_DIR, { withFileTypes: true });
  const projects: Project[] = [];

  for (const dir of dirs) {
    if (dir.isDirectory()) {
      try {
        const projectPath = path.join(PROJECTS_DIR, dir.name, 'project.md');
        const content = await fs.readFile(projectPath, 'utf-8');
        const { data } = matter(content);
        projects.push(data as Project);
      } catch {
        // Skip invalid project directories
      }
    }
  }

  return projects.sort((a, b) => 
    new Date(b.updatedAt).getTime() - new Date(a.updatedAt).getTime()
  );
}

export async function getProject(slug: string): Promise<Project | null> {
  try {
    const projectPath = path.join(PROJECTS_DIR, slug, 'project.md');
    const content = await fs.readFile(projectPath, 'utf-8');
    const { data } = matter(content);
    return data as Project;
  } catch {
    return null;
  }
}

export async function createProject(name: string): Promise<Project> {
  await ensureProjectsDir();
  
  const slug = slugify(name);
  const projectDir = path.join(PROJECTS_DIR, slug);
  
  // Verificar si ya existe
  try {
    await fs.access(projectDir);
    throw new Error(`El proyecto "${name}" ya existe`);
  } catch (e: any) {
    if (e.code !== 'ENOENT') throw e;
  }

  const now = new Date().toISOString();
  const project: Project = {
    id: crypto.randomUUID(),
    name,
    slug,
    createdAt: now,
    updatedAt: now,
    status: 'draft',
    currentStep: 'idea_motriz',
  };

  // Crear estructura de carpetas
  await fs.mkdir(projectDir, { recursive: true });
  await fs.mkdir(path.join(projectDir, 'capitulos'), { recursive: true });

  // Guardar proyecto
  const content = matter.stringify('', project);
  await fs.writeFile(path.join(projectDir, 'project.md'), content);

  return project;
}

export async function updateProject(slug: string, updates: Partial<Project>): Promise<Project> {
  const project = await getProject(slug);
  if (!project) throw new Error('Proyecto no encontrado');

  const updated = {
    ...project,
    ...updates,
    updatedAt: new Date().toISOString(),
  };

  const projectPath = path.join(PROJECTS_DIR, slug, 'project.md');
  const content = matter.stringify('', updated);
  await fs.writeFile(projectPath, content);

  return updated;
}

export async function deleteProject(slug: string): Promise<void> {
  const projectDir = path.join(PROJECTS_DIR, slug);
  await fs.rm(projectDir, { recursive: true, force: true });
}

// =====================
// IDEA MOTRIZ
// =====================

export async function getIdeaMotriz(slug: string): Promise<IdeaMotriz | null> {
  try {
    const filePath = path.join(PROJECTS_DIR, slug, 'idea-motriz.md');
    const content = await fs.readFile(filePath, 'utf-8');
    const { data, content: mdContent } = matter(content);
    return { ...data, concepto: mdContent } as IdeaMotriz;
  } catch {
    return null;
  }
}

export async function saveIdeaMotriz(slug: string, ideaMotriz: IdeaMotriz): Promise<void> {
  const filePath = path.join(PROJECTS_DIR, slug, 'idea-motriz.md');
  const { concepto, ...frontmatter } = ideaMotriz;
  const content = matter.stringify(concepto || '', frontmatter);
  await fs.writeFile(filePath, content);
  await updateProject(slug, { updatedAt: new Date().toISOString() });
}

// =====================
// PERSONAJES
// =====================

export async function getPersonajes(slug: string): Promise<Personaje[]> {
  try {
    const filePath = path.join(PROJECTS_DIR, slug, 'personajes.md');
    const content = await fs.readFile(filePath, 'utf-8');
    const { data } = matter(content);
    return data.personajes || [];
  } catch {
    return [];
  }
}

export async function savePersonajes(slug: string, personajes: Personaje[]): Promise<void> {
  const filePath = path.join(PROJECTS_DIR, slug, 'personajes.md');
  const content = matter.stringify('', { personajes });
  await fs.writeFile(filePath, content);
  await updateProject(slug, { updatedAt: new Date().toISOString() });
}

// =====================
// CAPÍTULOS
// =====================

export async function getCapitulos(slug: string): Promise<Capitulo[]> {
  try {
    const capitulosDir = path.join(PROJECTS_DIR, slug, 'capitulos');
    const dirs = await fs.readdir(capitulosDir, { withFileTypes: true });
    const capitulos: Capitulo[] = [];

    for (const dir of dirs) {
      if (dir.isDirectory()) {
        try {
          const capPath = path.join(capitulosDir, dir.name, 'capitulo.md');
          const content = await fs.readFile(capPath, 'utf-8');
          const { data } = matter(content);
          capitulos.push(data as Capitulo);
        } catch {
          // Skip invalid
        }
      }
    }

    return capitulos.sort((a, b) => a.numero - b.numero);
  } catch {
    return [];
  }
}

export async function createCapitulo(slug: string, numero: number, titulo: string): Promise<Capitulo> {
  const capSlug = `${String(numero).padStart(2, '0')}-${slugify(titulo)}`;
  const capDir = path.join(PROJECTS_DIR, slug, 'capitulos', capSlug);
  
  await fs.mkdir(capDir, { recursive: true });

  const capitulo: Capitulo = {
    id: crypto.randomUUID(),
    numero,
    titulo,
    virtudGanada: '',
    status: 'draft',
    currentStep: 'guion_conductor',
  };

  const content = matter.stringify('', capitulo);
  await fs.writeFile(path.join(capDir, 'capitulo.md'), content);

  return capitulo;
}

export async function getCapitulo(slug: string, capSlug: string): Promise<Capitulo | null> {
  try {
    const capPath = path.join(PROJECTS_DIR, slug, 'capitulos', capSlug, 'capitulo.md');
    const content = await fs.readFile(capPath, 'utf-8');
    const { data } = matter(content);
    return data as Capitulo;
  } catch {
    return null;
  }
}

// =====================
// GUIÓN CONDUCTOR
// =====================

export async function getGuionConductor(slug: string, capSlug: string): Promise<GuionConductor | null> {
  try {
    const filePath = path.join(PROJECTS_DIR, slug, 'capitulos', capSlug, 'guion.md');
    const content = await fs.readFile(filePath, 'utf-8');
    const { data } = matter(content);
    return data as GuionConductor;
  } catch {
    return null;
  }
}

export async function saveGuionConductor(slug: string, capSlug: string, guion: GuionConductor): Promise<void> {
  const filePath = path.join(PROJECTS_DIR, slug, 'capitulos', capSlug, 'guion.md');
  const content = matter.stringify('', guion);
  await fs.writeFile(filePath, content);
}

// =====================
// ESCALETA
// =====================

export async function getEscaleta(slug: string, capSlug: string): Promise<Escaleta | null> {
  try {
    const filePath = path.join(PROJECTS_DIR, slug, 'capitulos', capSlug, 'escaleta.md');
    const content = await fs.readFile(filePath, 'utf-8');
    const { data } = matter(content);
    return data as Escaleta;
  } catch {
    return null;
  }
}

export async function saveEscaleta(slug: string, capSlug: string, escaleta: Escaleta): Promise<void> {
  const filePath = path.join(PROJECTS_DIR, slug, 'capitulos', capSlug, 'escaleta.md');
  const content = matter.stringify('', escaleta);
  await fs.writeFile(filePath, content);
}

// =====================
// CHARACTER ASSETS MAP
// =====================

export interface CharacterAssetsSummary {
  hasAssets: boolean;
  tposeFrontUrl?: string;
  tposeSideUrl?: string;
  tposeBackUrl?: string;
  emotions: Partial<Record<EmotionVariant, string>>;
}

export async function getCharacterAssetsMap(
  slug: string,
  personajes: Personaje[]
): Promise<Record<string, CharacterAssetsSummary>> {
  const result: Record<string, CharacterAssetsSummary> = {};

  await Promise.all(personajes.map(async (p) => {
    const assetsPath = path.join(PROJECTS_DIR, slug, 'personajes', p.id, 'assets.json');
    try {
      const content = await fs.readFile(assetsPath, 'utf-8');
      const parsed = JSON.parse(content);
      const data: CharacterAssetsData = Array.isArray(parsed)
        ? { assets: parsed, baseLocked: false }
        : parsed;

      const tposeFront = data.assets.find(a => a.isBase && a.imageUrl)
        || data.assets.find(a => a.type === 'tpose' && a.variant === 'front' && a.imageUrl);
      const tposeSide = data.assets.find(a => a.type === 'tpose' && a.variant === 'side' && a.imageUrl);
      const tposeBack = data.assets.find(a => a.type === 'tpose' && a.variant === 'back' && a.imageUrl);

      const emotions: Partial<Record<EmotionVariant, string>> = {};
      for (const asset of data.assets) {
        if (asset.type === 'emotion' && asset.status === 'generated' && asset.imageUrl) {
          emotions[asset.variant as EmotionVariant] = asset.imageUrl;
        }
      }

      result[p.id] = {
        hasAssets: data.assets.some(a => a.status === 'generated'),
        tposeFrontUrl: tposeFront?.imageUrl,
        tposeSideUrl: tposeSide?.imageUrl,
        tposeBackUrl: tposeBack?.imageUrl,
        emotions,
      };
    } catch {
      result[p.id] = { hasAssets: false, emotions: {} };
    }
  }));

  return result;
}
