import { FastifyPluginAsync } from 'fastify';
import { z } from 'zod';
import { GitService } from '../services/git.service.js';
import { FileGeneratorService } from '../services/file-generator.service.js';
import { db } from '../config/database.js';
import { events, galleryImages, contentSections, publishHistory } from '../db/schema.js';
import { eq } from 'drizzle-orm';

// Fastify JSON schema for publish body
const publishBodyJsonSchema = {
  type: 'object',
  required: ['commitMessage'],
  properties: {
    commitMessage: { type: 'string', minLength: 1, maxLength: 200 },
  },
} as const;

const publishRoute: FastifyPluginAsync = async (fastify) => {
  fastify.post('/publish', {
    schema: {
      body: publishBodyJsonSchema,
    },
    preHandler: [fastify.authenticate],
  }, async (request, reply) => {
    try {
      const { commitMessage } = request.body as any;
      const userId = request.user.id;

      fastify.log.info('Starting publish process...');

      // Initialize git service
      const gitService = new GitService();
      await gitService.initialize();

      fastify.log.info('Git repository initialized');

      // Fetch all content from database
      const eventsData = await db
        .select()
        .from(events)
        .where(eq(events.isPublished, true))
        .orderBy(events.displayOrder);

      const galleryData = await db
        .select()
        .from(galleryImages)
        .where(eq(galleryImages.isPublished, true))
        .orderBy(galleryImages.displayOrder);

      const sectionsData = await db.select().from(contentSections);
      const sectionsMap = new Map<string, any>(
        (sectionsData as any[]).map((s: any) => [s.sectionName as string, s.contentJson as any])
      );

      fastify.log.info(`Fetched ${eventsData.length} events, ${galleryData.length} images, ${sectionsData.length} sections`);

      // Generate and write files
      const fileGenerator = new FileGeneratorService();
      await fileGenerator.writeFiles(
        gitService.getWorkspacePath(''),
        (eventsData as any[]).map((e: any) => ({
          title: e.title,
          date: e.date,
          description: e.description,
          imageUrl: e.imageUrl,
        })),
        (galleryData as any[]).map((g: any) => ({
          imageUrl: g.imageUrl,
          altText: g.altText,
        })),
        sectionsMap
      );

      fastify.log.info('Files generated successfully');

      // Commit and push
      const commitHash = await gitService.commitAndPush(commitMessage);

      fastify.log.info(`Changes committed: ${commitHash}`);

      // Record in history
      await db.insert(publishHistory).values({
        userId,
        commitHash,
        commitMessage,
      });

      return {
        success: true,
        commitHash,
        message: 'Changes published successfully',
      };

    } catch (error) {
      fastify.log.error({ err: error }, 'Publish error');

      // Attempt to reset git state on error
      try {
        const gitService = new GitService();
        await gitService.reset();
      } catch (resetError) {
        fastify.log.error({ err: resetError }, 'Failed to reset git state');
      }

      return reply.code(500).send({
        success: false,
        error: 'Failed to publish changes',
        details: error instanceof Error ? error.message : 'Unknown error',
      });
    }
  });

  // Get publish history
  fastify.get('/publish/history', {
    preHandler: [fastify.authenticate],
  }, async (request, reply) => {
    const history = await db
      .select()
      .from(publishHistory)
      .orderBy(publishHistory.publishedAt)
      .limit(20);

    return { history };
  });
};

export default publishRoute;
