// Package report - Output formatters
package report

import (
	"encoding/json"
	"fmt"
	"io"
	"strings"
	"text/template"
	"time"
)

// Formatter formats reports for output
type Formatter interface {
	Format(report *Report, w io.Writer) error
}

// JSONFormatter formats reports as JSON
type JSONFormatter struct {
	Indent bool
}

// Format writes the report as JSON
func (f *JSONFormatter) Format(report *Report, w io.Writer) error {
	var data []byte
	var err error

	if f.Indent {
		data, err = json.MarshalIndent(report, "", "  ")
	} else {
		data, err = json.Marshal(report)
	}

	if err != nil {
		return err
	}

	_, err = w.Write(data)
	return err
}

// MarkdownFormatter formats reports as Markdown
type MarkdownFormatter struct{}

// Format writes the report as Markdown
func (f *MarkdownFormatter) Format(report *Report, w io.Writer) error {
	tmpl := template.Must(template.New("report").Funcs(template.FuncMap{
		"statusIcon":   StatusIcon,
		"severityIcon": SeverityIcon,
		"formatTime":   func(t time.Time) string { return t.Format("2006-01-02 15:04:05") },
		"formatDate":   func(t time.Time) string { return t.Format("2006-01-02") },
		"upper":        strings.ToUpper,
	}).Parse(markdownTemplate))

	return tmpl.Execute(w, report)
}

const markdownTemplate = `# {{.Title}}

**Generated:** {{formatTime .GeneratedAt}}  
**Period:** {{formatDate .PeriodStart}} to {{formatDate .PeriodEnd}}  
**Overall Status:** {{statusIcon .Status}} {{.Status}}  
**Compliance Score:** {{printf "%.1f" .Score}}%

---

## Executive Summary

{{.Description}}

| Metric | Value |
|--------|-------|
| Total Controls | {{.Summary.TotalControls}} |
| Compliant | {{.Summary.CompliantControls}} |
| Non-Compliant | {{.Summary.NonCompliantControls}} |
| Partial | {{.Summary.PartialControls}} |
| Compliance Rate | {{printf "%.1f" .Summary.ComplianceRate}}% |
| Open Findings | {{.Summary.OpenFindings}} |
| Risk Score | {{printf "%.1f" .Summary.RiskScore}} |

---

## Compliance Categories

{{range .Categories}}
### {{statusIcon .Status}} {{.Name}}

**Status:** {{.Status}} | **Score:** {{printf "%.1f" .Score}}%

{{.Description}}

| Control | Reference | Status | Notes |
|---------|-----------|--------|-------|
{{range .Controls}}| {{.Name}} | {{.Reference}} | {{statusIcon .Status}} | {{.Notes}} |
{{end}}

{{end}}

---

## Findings

{{if .Findings}}
| ID | Severity | Title | Status |
|----|----------|-------|--------|
{{range .Findings}}| {{.ID}} | {{severityIcon .Severity}} {{.Severity}} | {{.Title}} | {{.Status}} |
{{end}}

### Finding Details

{{range .Findings}}
#### {{severityIcon .Severity}} {{.Title}}

- **ID:** {{.ID}}
- **Control:** {{.ControlID}}
- **Severity:** {{.Severity}}
- **Type:** {{.Type}}
- **Status:** {{.Status}}
- **Detected:** {{formatTime .DetectedAt}}

**Description:** {{.Description}}

**Impact:** {{.Impact}}

**Recommendation:** {{.Recommendation}}

---

{{end}}
{{else}}
No open findings.
{{end}}

---

## Evidence Summary

{{if .Evidence}}
| ID | Type | Description | Collected |
|----|------|-------------|-----------|
{{range .Evidence}}| {{.ID}} | {{.Type}} | {{.Description}} | {{formatTime .CollectedAt}} |
{{end}}
{{else}}
No evidence collected.
{{end}}

---

*Report generated by dbbackup compliance module*
`

// HTMLFormatter formats reports as HTML
type HTMLFormatter struct{}

// Format writes the report as HTML
func (f *HTMLFormatter) Format(report *Report, w io.Writer) error {
	tmpl := template.Must(template.New("report").Funcs(template.FuncMap{
		"statusIcon":    StatusIcon,
		"statusClass":   statusClass,
		"severityIcon":  SeverityIcon,
		"severityClass": severityClass,
		"formatTime":    func(t time.Time) string { return t.Format("2006-01-02 15:04:05") },
		"formatDate":    func(t time.Time) string { return t.Format("2006-01-02") },
	}).Parse(htmlTemplate))

	return tmpl.Execute(w, report)
}

func statusClass(s ComplianceStatus) string {
	switch s {
	case StatusCompliant:
		return "status-compliant"
	case StatusNonCompliant:
		return "status-noncompliant"
	case StatusPartial:
		return "status-partial"
	default:
		return "status-unknown"
	}
}

func severityClass(s FindingSeverity) string {
	switch s {
	case SeverityCritical:
		return "severity-critical"
	case SeverityHigh:
		return "severity-high"
	case SeverityMedium:
		return "severity-medium"
	case SeverityLow:
		return "severity-low"
	default:
		return "severity-unknown"
	}
}

const htmlTemplate = `<!DOCTYPE html>
<html lang="en">
<head>
    <meta charset="UTF-8">
    <meta name="viewport" content="width=device-width, initial-scale=1.0">
    <title>{{.Title}}</title>
    <style>
        :root {
            --color-compliant: #27ae60;
            --color-noncompliant: #e74c3c;
            --color-partial: #f39c12;
            --color-unknown: #95a5a6;
        }
        body {
            font-family: -apple-system, BlinkMacSystemFont, 'Segoe UI', Roboto, Oxygen, Ubuntu, sans-serif;
            line-height: 1.6;
            max-width: 1200px;
            margin: 0 auto;
            padding: 20px;
            background: #f5f5f5;
        }
        .report-header {
            background: white;
            padding: 30px;
            border-radius: 8px;
            box-shadow: 0 2px 4px rgba(0,0,0,0.1);
            margin-bottom: 20px;
        }
        .report-header h1 {
            margin: 0 0 10px 0;
            color: #2c3e50;
        }
        .report-meta {
            color: #7f8c8d;
            font-size: 0.9em;
        }
        .status-badge {
            display: inline-block;
            padding: 4px 12px;
            border-radius: 20px;
            font-weight: bold;
            font-size: 0.85em;
        }
        .status-compliant { background: var(--color-compliant); color: white; }
        .status-noncompliant { background: var(--color-noncompliant); color: white; }
        .status-partial { background: var(--color-partial); color: white; }
        .status-unknown { background: var(--color-unknown); color: white; }
        .score-display {
            font-size: 48px;
            font-weight: bold;
            color: #2c3e50;
        }
        .summary-grid {
            display: grid;
            grid-template-columns: repeat(auto-fit, minmax(150px, 1fr));
            gap: 20px;
            margin: 20px 0;
        }
        .summary-card {
            background: white;
            padding: 20px;
            border-radius: 8px;
            text-align: center;
            box-shadow: 0 2px 4px rgba(0,0,0,0.1);
        }
        .summary-card .value {
            font-size: 32px;
            font-weight: bold;
            color: #2c3e50;
        }
        .summary-card .label {
            color: #7f8c8d;
            font-size: 0.9em;
        }
        .section {
            background: white;
            padding: 20px;
            border-radius: 8px;
            box-shadow: 0 2px 4px rgba(0,0,0,0.1);
            margin-bottom: 20px;
        }
        .section h2 {
            margin-top: 0;
            color: #2c3e50;
            border-bottom: 2px solid #ecf0f1;
            padding-bottom: 10px;
        }
        .category {
            margin-bottom: 30px;
        }
        .category h3 {
            display: flex;
            align-items: center;
            gap: 10px;
        }
        table {
            width: 100%;
            border-collapse: collapse;
            margin: 10px 0;
        }
        th, td {
            padding: 12px;
            text-align: left;
            border-bottom: 1px solid #ecf0f1;
        }
        th {
            background: #f8f9fa;
            font-weight: 600;
        }
        tr:hover {
            background: #f8f9fa;
        }
        .finding-card {
            border-left: 4px solid var(--color-unknown);
            padding: 15px;
            margin: 15px 0;
            background: #f8f9fa;
            border-radius: 0 8px 8px 0;
        }
        .finding-card.severity-critical { border-color: #e74c3c; }
        .finding-card.severity-high { border-color: #e67e22; }
        .finding-card.severity-medium { border-color: #f39c12; }
        .finding-card.severity-low { border-color: #27ae60; }
        .finding-card h4 {
            margin: 0 0 10px 0;
        }
        .finding-meta {
            font-size: 0.85em;
            color: #7f8c8d;
        }
        .progress-bar {
            height: 8px;
            background: #ecf0f1;
            border-radius: 4px;
            overflow: hidden;
        }
        .progress-fill {
            height: 100%;
            background: var(--color-compliant);
            transition: width 0.3s ease;
        }
        .footer {
            text-align: center;
            color: #7f8c8d;
            padding: 20px;
            font-size: 0.85em;
        }
    </style>
</head>
<body>
    <div class="report-header">
        <h1>{{.Title}}</h1>
        <p class="report-meta">
            Generated: {{formatTime .GeneratedAt}} | 
            Period: {{formatDate .PeriodStart}} to {{formatDate .PeriodEnd}}
        </p>
        <div style="display: flex; align-items: center; gap: 20px; margin-top: 20px;">
            <div class="score-display">{{printf "%.0f" .Score}}%</div>
            <div>
                <span class="status-badge {{statusClass .Status}}">{{.Status}}</span>
                <p style="margin: 10px 0 0 0; color: #7f8c8d;">{{.Description}}</p>
            </div>
        </div>
    </div>

    <div class="summary-grid">
        <div class="summary-card">
            <div class="value">{{.Summary.TotalControls}}</div>
            <div class="label">Total Controls</div>
        </div>
        <div class="summary-card">
            <div class="value" style="color: var(--color-compliant);">{{.Summary.CompliantControls}}</div>
            <div class="label">Compliant</div>
        </div>
        <div class="summary-card">
            <div class="value" style="color: var(--color-noncompliant);">{{.Summary.NonCompliantControls}}</div>
            <div class="label">Non-Compliant</div>
        </div>
        <div class="summary-card">
            <div class="value" style="color: var(--color-partial);">{{.Summary.PartialControls}}</div>
            <div class="label">Partial</div>
        </div>
        <div class="summary-card">
            <div class="value">{{.Summary.OpenFindings}}</div>
            <div class="label">Open Findings</div>
        </div>
        <div class="summary-card">
            <div class="value">{{printf "%.1f" .Summary.RiskScore}}</div>
            <div class="label">Risk Score</div>
        </div>
    </div>

    <div class="section">
        <h2>Compliance Categories</h2>
        {{range .Categories}}
        <div class="category">
            <h3>
                {{statusIcon .Status}} {{.Name}}
                <span class="status-badge {{statusClass .Status}}">{{printf "%.0f" .Score}}%</span>
            </h3>
            <p style="color: #7f8c8d;">{{.Description}}</p>
            <div class="progress-bar">
                <div class="progress-fill" style="width: {{printf "%.0f" .Score}}%;"></div>
            </div>
            <table>
                <thead>
                    <tr>
                        <th>Control</th>
                        <th>Reference</th>
                        <th>Status</th>
                        <th>Notes</th>
                    </tr>
                </thead>
                <tbody>
                    {{range .Controls}}
                    <tr>
                        <td>{{.Name}}</td>
                        <td>{{.Reference}}</td>
                        <td>{{statusIcon .Status}}</td>
                        <td>{{.Notes}}</td>
                    </tr>
                    {{end}}
                </tbody>
            </table>
        </div>
        {{end}}
    </div>

    {{if .Findings}}
    <div class="section">
        <h2>Findings ({{len .Findings}})</h2>
        {{range .Findings}}
        <div class="finding-card {{severityClass .Severity}}">
            <h4>{{severityIcon .Severity}} {{.Title}}</h4>
            <div class="finding-meta">
                <strong>ID:</strong> {{.ID}} | 
                <strong>Severity:</strong> {{.Severity}} | 
                <strong>Status:</strong> {{.Status}} |
                <strong>Detected:</strong> {{formatTime .DetectedAt}}
            </div>
            <p><strong>Description:</strong> {{.Description}}</p>
            <p><strong>Impact:</strong> {{.Impact}}</p>
            <p><strong>Recommendation:</strong> {{.Recommendation}}</p>
        </div>
        {{end}}
    </div>
    {{end}}

    {{if .Evidence}}
    <div class="section">
        <h2>Evidence ({{len .Evidence}} items)</h2>
        <table>
            <thead>
                <tr>
                    <th>ID</th>
                    <th>Type</th>
                    <th>Description</th>
                    <th>Collected</th>
                </tr>
            </thead>
            <tbody>
                {{range .Evidence}}
                <tr>
                    <td>{{.ID}}</td>
                    <td>{{.Type}}</td>
                    <td>{{.Description}}</td>
                    <td>{{formatTime .CollectedAt}}</td>
                </tr>
                {{end}}
            </tbody>
        </table>
    </div>
    {{end}}

    <div class="footer">
        <p>Report generated by dbbackup compliance module</p>
        <p>Report ID: {{.ID}}</p>
    </div>
</body>
</html>`

// GetFormatter returns a formatter for the given format
func GetFormatter(format OutputFormat) Formatter {
	switch format {
	case FormatJSON:
		return &JSONFormatter{Indent: true}
	case FormatMarkdown:
		return &MarkdownFormatter{}
	case FormatHTML:
		return &HTMLFormatter{}
	default:
		return &JSONFormatter{Indent: true}
	}
}

// ConsoleFormatter formats reports for terminal output
type ConsoleFormatter struct{}

// Format writes the report to console
func (f *ConsoleFormatter) Format(report *Report, w io.Writer) error {
	// Header
	fmt.Fprintf(w, "\n%s\n", strings.Repeat("=", 60))
	fmt.Fprintf(w, "  %s\n", report.Title)
	fmt.Fprintf(w, "%s\n\n", strings.Repeat("=", 60))

	fmt.Fprintf(w, "  Generated: %s\n", report.GeneratedAt.Format("2006-01-02 15:04:05"))
	fmt.Fprintf(w, "  Period: %s to %s\n",
		report.PeriodStart.Format("2006-01-02"),
		report.PeriodEnd.Format("2006-01-02"))
	fmt.Fprintf(w, "  Status: %s %s\n", StatusIcon(report.Status), report.Status)
	fmt.Fprintf(w, "  Score: %.1f%%\n\n", report.Score)

	// Summary
	fmt.Fprintf(w, "  SUMMARY\n")
	fmt.Fprintf(w, "  %s\n", strings.Repeat("-", 40))
	fmt.Fprintf(w, "  Controls:       %d total, %d compliant, %d non-compliant\n",
		report.Summary.TotalControls,
		report.Summary.CompliantControls,
		report.Summary.NonCompliantControls)
	fmt.Fprintf(w, "  Compliance:     %.1f%%\n", report.Summary.ComplianceRate)
	fmt.Fprintf(w, "  Open Findings:  %d (critical: %d, high: %d)\n",
		report.Summary.OpenFindings,
		report.Summary.CriticalFindings,
		report.Summary.HighFindings)
	fmt.Fprintf(w, "  Risk Score:     %.1f\n\n", report.Summary.RiskScore)

	// Categories
	fmt.Fprintf(w, "  CATEGORIES\n")
	fmt.Fprintf(w, "  %s\n", strings.Repeat("-", 40))
	for _, cat := range report.Categories {
		fmt.Fprintf(w, "  %s %-25s %.0f%%\n", StatusIcon(cat.Status), cat.Name, cat.Score)
	}
	fmt.Fprintln(w)

	// Findings
	if len(report.Findings) > 0 {
		fmt.Fprintf(w, "  FINDINGS\n")
		fmt.Fprintf(w, "  %s\n", strings.Repeat("-", 40))
		for _, f := range report.Findings {
			fmt.Fprintf(w, "  %s [%s] %s\n", SeverityIcon(f.Severity), f.Severity, f.Title)
			fmt.Fprintf(w, "     %s\n", f.Description)
		}
		fmt.Fprintln(w)
	}

	fmt.Fprintf(w, "%s\n", strings.Repeat("=", 60))
	return nil
}
