package lib

import (
	"encoding/json"
	"fmt"
	"os"
	"strings"
)

type Paper struct {
	Title    string `json:"title"`
	ArxivID  string `json:"arxiv_id"`
	Abstract string `json:"abstract"`
}

type PaperDecision struct {
	Paper       Paper  `json:"paper"`
	Explanation string `json:"explanation"`
}

type DecisionData struct {
	Accepted []PaperDecision `json:"accepted"`
	Rejected []PaperDecision `json:"rejected"`
}

func ProcessJSONFile(inputPath string) (DecisionData, error) {
	var data DecisionData

	jsonFile, err := os.Open(inputPath)
	if err != nil {
		return data, fmt.Errorf("error opening input file: %w", err)
	}
	defer jsonFile.Close()

	// First try decoding as DecisionData format
	decoder := json.NewDecoder(jsonFile)
	if err := decoder.Decode(&data); err == nil {
		return data, nil
	}

	// Try alternative formats
	jsonData, err := os.ReadFile(inputPath)
	if err != nil {
		return data, fmt.Errorf("error reading input file: %w", err)
	}

	// Try array format with status field
	var papers []struct {
		Paper       Paper  `json:"paper"`
		Explanation string `json:"explanation"`
		Status      string `json:"status"`
	}
	if err := json.Unmarshal(jsonData, &papers); err == nil {
		for _, p := range papers {
			switch p.Status {
			case "accepted":
				data.Accepted = append(data.Accepted, PaperDecision{p.Paper, p.Explanation})
			case "rejected":
				data.Rejected = append(data.Rejected, PaperDecision{p.Paper, p.Explanation})
			default:
				fmt.Printf("Warning: Paper '%s' has unknown status '%s'\n", p.Paper.Title, p.Status)
			}
		}
		return data, nil
	}

	// Try original object format
	var objData struct {
		Accepted []PaperDecision `json:"accepted"`
		Rejected []PaperDecision `json:"rejected"`
	}
	if err := json.Unmarshal(jsonData, &objData); err != nil {
		return data, fmt.Errorf("error decoding JSON: %w", err)
	}

	data.Accepted = objData.Accepted
	data.Rejected = objData.Rejected
	return data, nil
}

func GenerateMarkdown(data DecisionData, outputPath string) error {
	file, err := os.Create(outputPath)
	if err != nil {
		return fmt.Errorf("error creating output file: %w", err)
	}
	defer file.Close()

	// Accepted Papers section
	fmt.Fprintln(file, "# Accepted Papers\n")
	for _, paper := range data.Accepted {
		writePaperSection(file, paper, "accepted")
	}

	// Rejected Papers section
	fmt.Fprintln(file, "# Rejected Papers\n")
	for _, paper := range data.Rejected {
		writePaperSection(file, paper, "rejected")
	}

	return nil
}

func writePaperSection(file *os.File, paper PaperDecision, decisionType string) {
	// Escape special characters in title
	title := strings.ReplaceAll(paper.Paper.Title, "[", "\\[")
	title = strings.ReplaceAll(title, "]", "\\]")

	fmt.Fprintf(file, "## [%s](https://arxiv.org/abs/%s)\n", title, paper.Paper.ArxivID)
	fmt.Fprintf(file, "**arXiv ID:** %s\n\n", paper.Paper.ArxivID)
	fmt.Fprintln(file, "**Abstract:**")

	// Format abstract as blockquote, handling multiple paragraphs
	abstract := strings.TrimSpace(paper.Paper.Abstract)
	paragraphs := strings.Split(abstract, "\n\n")
	for i, p := range paragraphs {
		// Ensure each line starts with >
		lines := strings.Split(strings.TrimSpace(p), "\n")
		for _, line := range lines {
			fmt.Fprintf(file, "> %s\n", strings.TrimSpace(line))
		}
		if i < len(paragraphs)-1 {
			fmt.Fprintln(file, ">")
		}
	}
	fmt.Fprintln(file)

	// Format explanation, ensuring it's properly escaped and formatted
	fmt.Fprintln(file, "**Decision Explanation:**")
	explanation := strings.TrimSpace(paper.Explanation)

	// If the explanation is already properly formatted (no raw JSON or code blocks),
	// write it directly
	fmt.Fprintf(file, "%s\n\n", explanation)

	fmt.Fprintln(file, "---\n")
}
