// src/utils/gitContributions.ts
import { dump } from 'js-yaml';

export interface ContributionData {
  type: 'add' | 'edit';
  tool: {
    name: string;
    icon?: string | null;
    type: 'software' | 'method' | 'concept';
    description: string;
    domains: string[];
    phases: string[];
    platforms: string[];
    skillLevel: string;
    accessType?: string | null;
    url: string;
    projectUrl?: string | null;
    license?: string | null;
    knowledgebase?: boolean | null;
    'domain-agnostic-software'?: string[] | null;
    related_concepts?: string[] | null;
    related_software?: string[] | null;
    tags: string[];
    statusUrl?: string | null;
  };
  metadata: {
    submitter: string;
    reason?: string;
    contact?: string; 
  };
}

export interface GitOperationResult {
  success: boolean;
  message: string;
  issueUrl?: string;
  issueNumber?: number;
}

interface KnowledgebaseContribution {
  toolName?: string;
  title?: string;
  description?: string;
  content?: string;
  externalLink?: string;
  difficulty?: string;
  categories?: string[];
  tags?: string[];
  uploadedFiles?: { name: string; url: string }[];
  submitter: string;
  reason?: string;
  contact?: string; 
}

interface GitConfig {
  provider: 'gitea' | 'github' | 'gitlab';
  apiEndpoint: string;
  apiToken: string;
  repoOwner: string;
  repoName: string;
}

export class GitContributionManager {
  private config: GitConfig;

  constructor() {
    const repoUrl = process.env.GIT_REPO_URL || '';
    const { owner, name } = this.parseRepoUrl(repoUrl);
    
    this.config = {
      provider: (process.env.GIT_PROVIDER as any) || 'gitea',
      apiEndpoint: process.env.GIT_API_ENDPOINT || '',
      apiToken: process.env.GIT_API_TOKEN || '',
      repoOwner: owner,
      repoName: name
    };

    if (!this.config.apiEndpoint || !this.config.apiToken) {
      throw new Error('Missing required git configuration');
    }
  }

  private parseRepoUrl(url: string): { owner: string; name: string } {
    const match = url.match(/\/([^\/]+)\/([^\/]+?)(?:\.git)?$/);
    if (!match) {
      throw new Error('Invalid repository URL format');
    }
    return { owner: match[1], name: match[2] };
  }

  async submitContribution(data: ContributionData): Promise<GitOperationResult> {
    try {
      const toolYaml = this.generateYAML(data.tool);
      const issueUrl = await this.createIssue(data, toolYaml);

      return {
        success: true,
        message: 'Tool contribution submitted as issue',
        issueUrl
      };
    } catch (error) {
      throw new Error(`Issue creation failed: ${error instanceof Error ? error.message : 'Unknown error'}`);
    }
  }

  async submitKnowledgebaseContribution(data: KnowledgebaseContribution): Promise<GitOperationResult> {
    try {
      const issueUrl = await this.createKnowledgebaseIssue(data);

      return {
        success: true,
        message: 'Knowledge base article submitted as issue',
        issueUrl
      };
    } catch (error) {
      throw new Error(`KB issue creation failed: ${error instanceof Error ? error.message : 'Unknown error'}`);
    }
  }

  private generateYAML(tool: any): string {
    const cleanTool: any = {
      name: tool.name,
      type: tool.type,
      description: tool.description,
      domains: tool.domains || [],
      phases: tool.phases || [],
      skillLevel: tool.skillLevel,
      url: tool.url
    };

    if (tool.icon) cleanTool.icon = tool.icon;
    if (tool.platforms?.length) cleanTool.platforms = tool.platforms;
    if (tool.license) cleanTool.license = tool.license;
    if (tool.accessType) cleanTool.accessType = tool.accessType;
    if (tool.projectUrl) cleanTool.projectUrl = tool.projectUrl;
    if (tool.knowledgebase) cleanTool.knowledgebase = tool.knowledgebase;
    if (tool.related_concepts?.length) cleanTool.related_concepts = tool.related_concepts;
    if (tool.related_software?.length) cleanTool.related_software = tool.related_software;
    if (tool.tags?.length) cleanTool.tags = tool.tags;
    if (tool['domain-agnostic-software']?.length) {
      cleanTool['domain-agnostic-software'] = tool['domain-agnostic-software'];
    }

    return dump(cleanTool, {
      lineWidth: -1,
      noRefs: true,
      quotingType: '"',
      forceQuotes: false,
      indent: 2
    }).trim();
  }

  private async createIssue(data: ContributionData, toolYaml: string): Promise<string> {
    const title = `${data.type === 'add' ? 'Add' : 'Update'} tool: ${data.tool.name}`;
    const body = this.generateIssueBody(data, toolYaml);

    let apiUrl: string;
    let requestBody: any;

    switch (this.config.provider) {
      case 'gitea':
        apiUrl = `${this.config.apiEndpoint}/repos/${this.config.repoOwner}/${this.config.repoName}/issues`;
        requestBody = { title, body };
        break;
      
      case 'github':
        apiUrl = `${this.config.apiEndpoint}/repos/${this.config.repoOwner}/${this.config.repoName}/issues`;
        requestBody = { title, body };
        break;
        
      case 'gitlab':
        apiUrl = `${this.config.apiEndpoint}/projects/${encodeURIComponent(this.config.repoOwner + '/' + this.config.repoName)}/issues`;
        requestBody = { title, description: body };
        break;
        
      default:
        throw new Error(`Unsupported git provider: ${this.config.provider}`);
    }

    const response = await fetch(apiUrl, {
      method: 'POST',
      headers: {
        'Authorization': `Bearer ${this.config.apiToken}`,
        'Content-Type': 'application/json'
      },
      body: JSON.stringify(requestBody)
    });

    if (!response.ok) {
      const errorText = await response.text();
      throw new Error(`HTTP ${response.status}: ${errorText}`);
    }

    const issueData = await response.json();
    
    switch (this.config.provider) {
      case 'gitea':
      case 'github':
        return issueData.html_url || issueData.url;
      case 'gitlab':
        return issueData.web_url;
      default:
        throw new Error('Unknown provider response format');
    }
  }

  private async createKnowledgebaseIssue(data: KnowledgebaseContribution): Promise<string> {
    const title = `Knowledge Base: ${data.title || data.toolName || 'New Article'}`;
    const body = this.generateKnowledgebaseIssueBody(data);

    let apiUrl: string;
    let requestBody: any;

    switch (this.config.provider) {
      case 'gitea':
        apiUrl = `${this.config.apiEndpoint}/repos/${this.config.repoOwner}/${this.config.repoName}/issues`;
        requestBody = { title, body };
        break;
      
      case 'github':
        apiUrl = `${this.config.apiEndpoint}/repos/${this.config.repoOwner}/${this.config.repoName}/issues`;
        requestBody = { title, body };
        break;
        
      case 'gitlab':
        apiUrl = `${this.config.apiEndpoint}/projects/${encodeURIComponent(this.config.repoOwner + '/' + this.config.repoName)}/issues`;
        requestBody = { title, description: body };
        break;
        
      default:
        throw new Error(`Unsupported git provider: ${this.config.provider}`);
    }

    const response = await fetch(apiUrl, {
      method: 'POST',
      headers: {
        'Authorization': `Bearer ${this.config.apiToken}`,
        'Content-Type': 'application/json'
      },
      body: JSON.stringify(requestBody)
    });

    if (!response.ok) {
      const errorText = await response.text();
      throw new Error(`HTTP ${response.status}: ${errorText}`);
    }

    const issueData = await response.json();
    
    switch (this.config.provider) {
      case 'gitea':
      case 'github':
        return issueData.html_url || issueData.url;
      case 'gitlab':
        return issueData.web_url;
      default:
        throw new Error('Unknown provider response format');
    }
  }

  private generateIssueBody(data: ContributionData, toolYaml: string): string {
    return `## ${data.type === 'add' ? 'Add' : 'Update'} Tool: ${data.tool.name}

**Submitted by:** ${data.metadata.submitter}  
**Type:** ${data.tool.type}  
**Action:** ${data.type}

### Tool Information
- **Name:** ${data.tool.name}
- **Description:** ${data.tool.description}
- **URL:** ${data.tool.url}
- **Skill Level:** ${data.tool.skillLevel}
${data.tool.platforms?.length ? `- **Platforms:** ${data.tool.platforms.join(', ')}` : ''}
${data.tool.license ? `- **License:** ${data.tool.license}` : ''}
${data.tool.domains?.length ? `- **Domains:** ${data.tool.domains.join(', ')}` : ''}
${data.tool.phases?.length ? `- **Phases:** ${data.tool.phases.join(', ')}` : ''}
${data.tool.related_concepts?.length ? `- **Related Concepts:** ${data.tool.related_concepts.join(', ')}` : ''}
${data.tool.related_software?.length ? `- **Related Software:** ${data.tool.related_software.join(', ')}` : ''}

${data.metadata.reason ? `### Reason
${data.metadata.reason}

` : ''}${data.metadata.contact ? `### Contact
${data.metadata.contact}


` : ''}### Copy-Paste YAML

\`\`\`yaml
  - ${toolYaml.split('\n').join('\n    ')}
\`\`\`

### For Maintainers
1. Copy the YAML above
2. Add to \`src/data/tools.yaml\` in the tools array
3. Maintain alphabetical order
4. Close this issue when done

---
*Submitted via ForensicPathways contribution form*`;
  }

  private generateKnowledgebaseIssueBody(data: KnowledgebaseContribution): string {
    const sections: string[] = [];

    sections.push(`## Knowledge Base Article: ${data.title ?? 'Untitled'}`);
    sections.push('');
    sections.push(`**Submitted by:** ${data.submitter}`);
    if (data.contact) sections.push(`**Contact:** ${data.contact}`);
    if (data.toolName)   sections.push(`**Related Tool:** ${data.toolName}`);
    if (data.difficulty) sections.push(`**Difficulty:** ${data.difficulty}`);
    sections.push('');

    if (data.description) {
      sections.push('### Description');
      sections.push(data.description);
      sections.push('');
    }

    if (data.content) {
      sections.push('### Article Content');
      sections.push('```markdown');
      sections.push(data.content);
      sections.push('```');
      sections.push('');
    }

    if (data.externalLink) {
      sections.push('### External Resource');
      sections.push(`- [External Documentation](${data.externalLink})`);
      sections.push('');
    }

    if (Array.isArray(data.uploadedFiles) && data.uploadedFiles.length) {
      sections.push('### Uploaded Files');
      data.uploadedFiles.forEach((file) => {
        const fileType = file.name.toLowerCase();
        let icon = '📎';

        if (fileType.endsWith('.pdf'))                       icon = '📄';
        else if (/(png|jpe?g|gif|webp)$/.test(fileType))     icon = '🖼️';
        else if (/(mp4|webm|mov|avi)$/.test(fileType))       icon = '🎥';
        else if (/(docx?)$/.test(fileType))                  icon = '📝';
        else if (/(zip|tar|gz)$/.test(fileType))             icon = '📦';

        sections.push(`- ${icon} [${file.name}](${file.url})`);
      });
      sections.push('');
    }

    const hasCategories = Array.isArray(data.categories) && data.categories.length > 0;
    const hasTags       = Array.isArray(data.tags)       && data.tags.length > 0;

    if (hasCategories || hasTags) {
      sections.push('### Metadata');
      if (hasCategories) sections.push(`**Categories:** ${data.categories!.join(', ')}`);
      if (hasTags)       sections.push(`**Tags:** ${data.tags!.join(', ')}`);
      sections.push('');
    }

    if (data.reason) {
      sections.push('### Reason for Contribution');
      sections.push(data.reason);
      sections.push('');
    }

    sections.push('### For Maintainers');
    sections.push('1. Review the content for quality and accuracy');
    sections.push('2. Create the appropriate markdown file in `src/content/knowledgebase/`');
    sections.push('3. Process any uploaded files as needed');
    sections.push('4. Close this issue when the article is published');
    sections.push('');
    sections.push('---');
    sections.push('*Submitted via ForensicPathways knowledge base contribution form*');

    return sections.join('\n');
  }
}