 
import { prisma } from '../db';
import { isValidRepositoryUrl, REPO_URL_ERROR_MESSAGE } from '../lib/repositoryUrlValidation';
import { logger } from '../logging/logger';

export class RepositoryService {
  /**
   * Initialize default repositories if they don't exist
   */
  async initializeDefaultRepositories(): Promise<void> {
    const mainRepoUrl = 'https://github.com/community-scripts/ProxmoxVE';
    const devRepoUrl = 'https://github.com/community-scripts/ProxmoxVED';

    // Check if repositories already exist
    const existingRepos = await prisma.repository.findMany({
      where: {
        url: {
          in: [mainRepoUrl, devRepoUrl]
        }
      }
    });

    const existingUrls = new Set(existingRepos.map((r: { url: string }) => r.url));

    // Create main repo if it doesn't exist
    if (!existingUrls.has(mainRepoUrl)) {
      await prisma.repository.create({
        data: {
          url: mainRepoUrl,
          enabled: true,
          is_default: true,
          is_removable: false,
          priority: 1
        }
      });
      logger.info('Initialized main repository:', { value: mainRepoUrl });
    }

    // Create dev repo if it doesn't exist
    if (!existingUrls.has(devRepoUrl)) {
      await prisma.repository.create({
        data: {
          url: devRepoUrl,
          enabled: false,
          is_default: true,
          is_removable: false,
          priority: 2
        }
      });
      logger.info('Initialized dev repository:', { value: devRepoUrl });
    }
  }

  /**
   * Get all repositories, sorted by priority
   */
  async getAllRepositories() {
    return await prisma.repository.findMany({
      orderBy: [
        { priority: 'asc' },
        { created_at: 'asc' }
      ]
    });
  }

  /**
   * Get enabled repositories, sorted by priority
   */
  async getEnabledRepositories() {
    return await prisma.repository.findMany({
      where: {
        enabled: true
      },
      orderBy: [
        { priority: 'asc' },
        { created_at: 'asc' }
      ]
    });
  }

  /**
   * Get repository by URL
   */
  async getRepositoryByUrl(url: string) {
    return await prisma.repository.findUnique({
      where: { url }
    });
  }

  /**
   * Create a new repository
   */
  async createRepository(data: {
    url: string;
    enabled?: boolean;
    priority?: number;
  }) {
    if (!isValidRepositoryUrl(data.url)) {
      throw new Error(REPO_URL_ERROR_MESSAGE);
    }

    // Check for duplicates
    const existing = await this.getRepositoryByUrl(data.url);
    if (existing) {
      throw new Error('Repository already exists');
    }

    // Get max priority for user-added repos
    const maxPriority = await prisma.repository.aggregate({
      _max: {
        priority: true
      }
    });

    return await prisma.repository.create({
      data: {
        url: data.url,
        enabled: data.enabled ?? true,
        is_default: false,
        is_removable: true,
        priority: data.priority ?? (maxPriority._max.priority ?? 0) + 1
      }
    });
  }

  /**
   * Update repository
   */
  async updateRepository(id: number, data: {
    enabled?: boolean;
    url?: string;
    priority?: number;
  }) {
    if (data.url) {
      if (!isValidRepositoryUrl(data.url)) {
        throw new Error(REPO_URL_ERROR_MESSAGE);
      }

      // Check for duplicates (excluding current repo)
      const existing = await prisma.repository.findFirst({
        where: {
          url: data.url,
          id: { not: id }
        }
      });
      if (existing) {
        throw new Error('Repository URL already exists');
      }
    }

    return await prisma.repository.update({
      where: { id },
      data
    });
  }

  /**
   * Delete repository and associated JSON files
   */
  async deleteRepository(id: number) {
    const repo = await prisma.repository.findUnique({
      where: { id }
    });

    if (!repo) {
      throw new Error('Repository not found');
    }

    if (!repo.is_removable) {
      throw new Error('Cannot delete default repository');
    }

    // Delete associated JSON files
    await this.deleteRepositoryJsonFiles(repo.url);

    // Delete repository
    await prisma.repository.delete({
      where: { id }
    });

    return { success: true };
  }

  /**
   * Delete all JSON files associated with a repository
   */
  private async deleteRepositoryJsonFiles(repoUrl: string): Promise<void> {
    const { readdir, unlink, readFile } = await import('fs/promises');
    const { join } = await import('path');

    const jsonDirectory = join(process.cwd(), 'scripts', 'json');

    try {
      const files = await readdir(jsonDirectory);
      
      for (const file of files) {
        if (!file.endsWith('.json')) continue;

        try {
          const filePath = join(jsonDirectory, file);
          const content = await readFile(filePath, 'utf-8');
          const script = JSON.parse(content);

          // If script has repository_url matching the repo, delete it
          if (script.repository_url === repoUrl) {
            await unlink(filePath);
            logger.info(`Deleted JSON file: ${file} (from repository: ${repoUrl})`);
          }
        } catch (error) {
          // Skip files that can't be read or parsed
          logger.error(`Error processing file ${file}:`, undefined, error);
        }
      }
    } catch (error) {
      // Directory might not exist, which is fine
      if ((error as NodeJS.ErrnoException).code !== 'ENOENT') {
        logger.error('Error deleting repository JSON files:', undefined, error);
      }
    }
  }
}

// Singleton instance
export const repositoryService = new RepositoryService();

