package diff

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

// OutputFormat represents the output format for diff results
type OutputFormat string

const (
	FormatSummary OutputFormat = "summary"
	FormatJSON    OutputFormat = "json"
	FormatHTML    OutputFormat = "html"
)

// FormatDiff formats the diff result according to the specified format
func FormatDiff(result *DiffResult, format OutputFormat, w io.Writer) error {
	switch format {
	case FormatSummary:
		return formatSummary(result, w)
	case FormatJSON:
		return formatJSON(result, w)
	case FormatHTML:
		return formatHTML(result, w)
	default:
		return fmt.Errorf("unsupported format: %s", format)
	}
}

func formatSummary(result *DiffResult, w io.Writer) error {
	summary := ComputeSummary(result)

	fmt.Fprintf(w, "\n=== Database Diff Summary ===\n")
	fmt.Fprintf(w, "Source: %s\n", result.Source)
	fmt.Fprintf(w, "Target: %s\n\n", result.Target)

	// Schemas
	if summary.Schemas.Missing > 0 || summary.Schemas.Extra > 0 || summary.Schemas.Modified > 0 {
		fmt.Fprintf(w, "Schemas:\n")
		if summary.Schemas.Missing > 0 {
			fmt.Fprintf(w, "  Missing:  %d\n", summary.Schemas.Missing)
		}
		if summary.Schemas.Extra > 0 {
			fmt.Fprintf(w, "  Extra:    %d\n", summary.Schemas.Extra)
		}
		if summary.Schemas.Modified > 0 {
			fmt.Fprintf(w, "  Modified: %d\n", summary.Schemas.Modified)
		}
		fmt.Fprintf(w, "\n")
	}

	// Tables
	if summary.Tables.Missing > 0 || summary.Tables.Extra > 0 || summary.Tables.Modified > 0 {
		fmt.Fprintf(w, "Tables:\n")
		if summary.Tables.Missing > 0 {
			fmt.Fprintf(w, "  Missing:  %d\n", summary.Tables.Missing)
		}
		if summary.Tables.Extra > 0 {
			fmt.Fprintf(w, "  Extra:    %d\n", summary.Tables.Extra)
		}
		if summary.Tables.Modified > 0 {
			fmt.Fprintf(w, "  Modified: %d\n", summary.Tables.Modified)
		}
		fmt.Fprintf(w, "\n")
	}

	// Columns
	if summary.Columns.Missing > 0 || summary.Columns.Extra > 0 || summary.Columns.Modified > 0 {
		fmt.Fprintf(w, "Columns:\n")
		if summary.Columns.Missing > 0 {
			fmt.Fprintf(w, "  Missing:  %d\n", summary.Columns.Missing)
		}
		if summary.Columns.Extra > 0 {
			fmt.Fprintf(w, "  Extra:    %d\n", summary.Columns.Extra)
		}
		if summary.Columns.Modified > 0 {
			fmt.Fprintf(w, "  Modified: %d\n", summary.Columns.Modified)
		}
		fmt.Fprintf(w, "\n")
	}

	// Indexes
	if summary.Indexes.Missing > 0 || summary.Indexes.Extra > 0 || summary.Indexes.Modified > 0 {
		fmt.Fprintf(w, "Indexes:\n")
		if summary.Indexes.Missing > 0 {
			fmt.Fprintf(w, "  Missing:  %d\n", summary.Indexes.Missing)
		}
		if summary.Indexes.Extra > 0 {
			fmt.Fprintf(w, "  Extra:    %d\n", summary.Indexes.Extra)
		}
		if summary.Indexes.Modified > 0 {
			fmt.Fprintf(w, "  Modified: %d\n", summary.Indexes.Modified)
		}
		fmt.Fprintf(w, "\n")
	}

	// Constraints
	if summary.Constraints.Missing > 0 || summary.Constraints.Extra > 0 || summary.Constraints.Modified > 0 {
		fmt.Fprintf(w, "Constraints:\n")
		if summary.Constraints.Missing > 0 {
			fmt.Fprintf(w, "  Missing:  %d\n", summary.Constraints.Missing)
		}
		if summary.Constraints.Extra > 0 {
			fmt.Fprintf(w, "  Extra:    %d\n", summary.Constraints.Extra)
		}
		if summary.Constraints.Modified > 0 {
			fmt.Fprintf(w, "  Modified: %d\n", summary.Constraints.Modified)
		}
		fmt.Fprintf(w, "\n")
	}

	// Relationships
	if summary.Relationships.Missing > 0 || summary.Relationships.Extra > 0 || summary.Relationships.Modified > 0 {
		fmt.Fprintf(w, "Relationships:\n")
		if summary.Relationships.Missing > 0 {
			fmt.Fprintf(w, "  Missing:  %d\n", summary.Relationships.Missing)
		}
		if summary.Relationships.Extra > 0 {
			fmt.Fprintf(w, "  Extra:    %d\n", summary.Relationships.Extra)
		}
		if summary.Relationships.Modified > 0 {
			fmt.Fprintf(w, "  Modified: %d\n", summary.Relationships.Modified)
		}
		fmt.Fprintf(w, "\n")
	}

	// Views
	if summary.Views.Missing > 0 || summary.Views.Extra > 0 || summary.Views.Modified > 0 {
		fmt.Fprintf(w, "Views:\n")
		if summary.Views.Missing > 0 {
			fmt.Fprintf(w, "  Missing:  %d\n", summary.Views.Missing)
		}
		if summary.Views.Extra > 0 {
			fmt.Fprintf(w, "  Extra:    %d\n", summary.Views.Extra)
		}
		if summary.Views.Modified > 0 {
			fmt.Fprintf(w, "  Modified: %d\n", summary.Views.Modified)
		}
		fmt.Fprintf(w, "\n")
	}

	// Sequences
	if summary.Sequences.Missing > 0 || summary.Sequences.Extra > 0 || summary.Sequences.Modified > 0 {
		fmt.Fprintf(w, "Sequences:\n")
		if summary.Sequences.Missing > 0 {
			fmt.Fprintf(w, "  Missing:  %d\n", summary.Sequences.Missing)
		}
		if summary.Sequences.Extra > 0 {
			fmt.Fprintf(w, "  Extra:    %d\n", summary.Sequences.Extra)
		}
		if summary.Sequences.Modified > 0 {
			fmt.Fprintf(w, "  Modified: %d\n", summary.Sequences.Modified)
		}
		fmt.Fprintf(w, "\n")
	}

	// Scripts
	if summary.Scripts.Missing > 0 || summary.Scripts.Extra > 0 || summary.Scripts.Modified > 0 {
		fmt.Fprintf(w, "Scripts:\n")
		if summary.Scripts.Missing > 0 {
			fmt.Fprintf(w, "  Missing:  %d\n", summary.Scripts.Missing)
		}
		if summary.Scripts.Extra > 0 {
			fmt.Fprintf(w, "  Extra:    %d\n", summary.Scripts.Extra)
		}
		if summary.Scripts.Modified > 0 {
			fmt.Fprintf(w, "  Modified: %d\n", summary.Scripts.Modified)
		}
		fmt.Fprintf(w, "\n")
	}

	// Check if there are no differences
	if summary.Schemas.Missing == 0 && summary.Schemas.Extra == 0 && summary.Schemas.Modified == 0 &&
		summary.Tables.Missing == 0 && summary.Tables.Extra == 0 && summary.Tables.Modified == 0 &&
		summary.Columns.Missing == 0 && summary.Columns.Extra == 0 && summary.Columns.Modified == 0 &&
		summary.Indexes.Missing == 0 && summary.Indexes.Extra == 0 && summary.Indexes.Modified == 0 &&
		summary.Constraints.Missing == 0 && summary.Constraints.Extra == 0 && summary.Constraints.Modified == 0 &&
		summary.Relationships.Missing == 0 && summary.Relationships.Extra == 0 && summary.Relationships.Modified == 0 &&
		summary.Views.Missing == 0 && summary.Views.Extra == 0 && summary.Views.Modified == 0 &&
		summary.Sequences.Missing == 0 && summary.Sequences.Extra == 0 && summary.Sequences.Modified == 0 &&
		summary.Scripts.Missing == 0 && summary.Scripts.Extra == 0 && summary.Scripts.Modified == 0 {
		fmt.Fprintf(w, "No differences found.\n")
	}

	return nil
}

func formatJSON(result *DiffResult, w io.Writer) error {
	encoder := json.NewEncoder(w)
	encoder.SetIndent("", "  ")
	return encoder.Encode(result)
}

func formatHTML(result *DiffResult, w io.Writer) error {
	tmpl, err := template.New("diff").Funcs(template.FuncMap{
		"join": strings.Join,
	}).Parse(htmlTemplate)
	if err != nil {
		return fmt.Errorf("failed to parse template: %w", err)
	}

	summary := ComputeSummary(result)
	data := struct {
		Result  *DiffResult
		Summary *Summary
	}{
		Result:  result,
		Summary: summary,
	}

	return tmpl.Execute(w, data)
}

const htmlTemplate = `<!DOCTYPE html>
<html lang="en">
<head>
    <meta charset="UTF-8">
    <meta name="viewport" content="width=device-width, initial-scale=1.0">
    <title>Database Diff Report</title>
    <style>
        body {
            font-family: -apple-system, BlinkMacSystemFont, 'Segoe UI', Roboto, Oxygen, Ubuntu, Cantarell, sans-serif;
            line-height: 1.6;
            max-width: 1200px;
            margin: 0 auto;
            padding: 20px;
            background-color: #f5f5f5;
        }
        h1, h2, h3 {
            color: #333;
        }
        .summary {
            background: white;
            border-radius: 8px;
            padding: 20px;
            margin-bottom: 20px;
            box-shadow: 0 2px 4px rgba(0,0,0,0.1);
        }
        .summary-grid {
            display: grid;
            grid-template-columns: repeat(auto-fit, minmax(200px, 1fr));
            gap: 15px;
            margin-top: 20px;
        }
        .summary-item {
            padding: 15px;
            background: #f8f9fa;
            border-radius: 6px;
            border-left: 4px solid #007bff;
        }
        .summary-item h3 {
            margin: 0 0 10px 0;
            font-size: 14px;
            text-transform: uppercase;
            color: #666;
        }
        .count-group {
            display: flex;
            justify-content: space-between;
            margin-top: 8px;
        }
        .count {
            display: flex;
            flex-direction: column;
            align-items: center;
        }
        .count-label {
            font-size: 12px;
            color: #666;
            margin-bottom: 4px;
        }
        .count-value {
            font-size: 20px;
            font-weight: bold;
        }
        .missing { color: #dc3545; }
        .extra { color: #28a745; }
        .modified { color: #ffc107; }
        .details {
            background: white;
            border-radius: 8px;
            padding: 20px;
            margin-bottom: 20px;
            box-shadow: 0 2px 4px rgba(0,0,0,0.1);
        }
        .schema-section {
            margin-bottom: 30px;
        }
        .table-section {
            margin-left: 20px;
            margin-bottom: 20px;
        }
        .item-list {
            list-style: none;
            padding: 0;
        }
        .item-list li {
            padding: 8px 12px;
            margin: 4px 0;
            background: #f8f9fa;
            border-radius: 4px;
            border-left: 3px solid #ccc;
        }
        .item-list li.missing {
            border-left-color: #dc3545;
            background: #fff5f5;
        }
        .item-list li.extra {
            border-left-color: #28a745;
            background: #f0fff4;
        }
        .item-list li.modified {
            border-left-color: #ffc107;
            background: #fffbf0;
        }
        .badge {
            display: inline-block;
            padding: 2px 8px;
            border-radius: 3px;
            font-size: 12px;
            font-weight: 600;
            margin-left: 8px;
        }
        .badge.missing { background: #dc3545; color: white; }
        .badge.extra { background: #28a745; color: white; }
        .badge.modified { background: #ffc107; color: #333; }
        .no-diff {
            text-align: center;
            padding: 40px;
            color: #28a745;
            font-size: 18px;
        }
    </style>
</head>
<body>
    <h1>Database Diff Report</h1>

    <div class="summary">
        <h2>Summary</h2>
        <p><strong>Source:</strong> {{.Result.Source}}</p>
        <p><strong>Target:</strong> {{.Result.Target}}</p>

        <div class="summary-grid">
            {{if or .Summary.Schemas.Missing .Summary.Schemas.Extra .Summary.Schemas.Modified}}
            <div class="summary-item">
                <h3>Schemas</h3>
                <div class="count-group">
                    <div class="count">
                        <span class="count-label">Missing</span>
                        <span class="count-value missing">{{.Summary.Schemas.Missing}}</span>
                    </div>
                    <div class="count">
                        <span class="count-label">Extra</span>
                        <span class="count-value extra">{{.Summary.Schemas.Extra}}</span>
                    </div>
                    <div class="count">
                        <span class="count-label">Modified</span>
                        <span class="count-value modified">{{.Summary.Schemas.Modified}}</span>
                    </div>
                </div>
            </div>
            {{end}}

            {{if or .Summary.Tables.Missing .Summary.Tables.Extra .Summary.Tables.Modified}}
            <div class="summary-item">
                <h3>Tables</h3>
                <div class="count-group">
                    <div class="count">
                        <span class="count-label">Missing</span>
                        <span class="count-value missing">{{.Summary.Tables.Missing}}</span>
                    </div>
                    <div class="count">
                        <span class="count-label">Extra</span>
                        <span class="count-value extra">{{.Summary.Tables.Extra}}</span>
                    </div>
                    <div class="count">
                        <span class="count-label">Modified</span>
                        <span class="count-value modified">{{.Summary.Tables.Modified}}</span>
                    </div>
                </div>
            </div>
            {{end}}

            {{if or .Summary.Columns.Missing .Summary.Columns.Extra .Summary.Columns.Modified}}
            <div class="summary-item">
                <h3>Columns</h3>
                <div class="count-group">
                    <div class="count">
                        <span class="count-label">Missing</span>
                        <span class="count-value missing">{{.Summary.Columns.Missing}}</span>
                    </div>
                    <div class="count">
                        <span class="count-label">Extra</span>
                        <span class="count-value extra">{{.Summary.Columns.Extra}}</span>
                    </div>
                    <div class="count">
                        <span class="count-label">Modified</span>
                        <span class="count-value modified">{{.Summary.Columns.Modified}}</span>
                    </div>
                </div>
            </div>
            {{end}}

            {{if or .Summary.Indexes.Missing .Summary.Indexes.Extra .Summary.Indexes.Modified}}
            <div class="summary-item">
                <h3>Indexes</h3>
                <div class="count-group">
                    <div class="count">
                        <span class="count-label">Missing</span>
                        <span class="count-value missing">{{.Summary.Indexes.Missing}}</span>
                    </div>
                    <div class="count">
                        <span class="count-label">Extra</span>
                        <span class="count-value extra">{{.Summary.Indexes.Extra}}</span>
                    </div>
                    <div class="count">
                        <span class="count-label">Modified</span>
                        <span class="count-value modified">{{.Summary.Indexes.Modified}}</span>
                    </div>
                </div>
            </div>
            {{end}}

            {{if or .Summary.Constraints.Missing .Summary.Constraints.Extra .Summary.Constraints.Modified}}
            <div class="summary-item">
                <h3>Constraints</h3>
                <div class="count-group">
                    <div class="count">
                        <span class="count-label">Missing</span>
                        <span class="count-value missing">{{.Summary.Constraints.Missing}}</span>
                    </div>
                    <div class="count">
                        <span class="count-label">Extra</span>
                        <span class="count-value extra">{{.Summary.Constraints.Extra}}</span>
                    </div>
                    <div class="count">
                        <span class="count-label">Modified</span>
                        <span class="count-value modified">{{.Summary.Constraints.Modified}}</span>
                    </div>
                </div>
            </div>
            {{end}}

            {{if or .Summary.Sequences.Missing .Summary.Sequences.Extra .Summary.Sequences.Modified}}
            <div class="summary-item">
                <h3>Sequences</h3>
                <div class="count-group">
                    <div class="count">
                        <span class="count-label">Missing</span>
                        <span class="count-value missing">{{.Summary.Sequences.Missing}}</span>
                    </div>
                    <div class="count">
                        <span class="count-label">Extra</span>
                        <span class="count-value extra">{{.Summary.Sequences.Extra}}</span>
                    </div>
                    <div class="count">
                        <span class="count-label">Modified</span>
                        <span class="count-value modified">{{.Summary.Sequences.Modified}}</span>
                    </div>
                </div>
            </div>
            {{end}}

            {{if or .Summary.Scripts.Missing .Summary.Scripts.Extra .Summary.Scripts.Modified}}
            <div class="summary-item">
                <h3>Scripts</h3>
                <div class="count-group">
                    <div class="count">
                        <span class="count-label">Missing</span>
                        <span class="count-value missing">{{.Summary.Scripts.Missing}}</span>
                    </div>
                    <div class="count">
                        <span class="count-label">Extra</span>
                        <span class="count-value extra">{{.Summary.Scripts.Extra}}</span>
                    </div>
                    <div class="count">
                        <span class="count-label">Modified</span>
                        <span class="count-value modified">{{.Summary.Scripts.Modified}}</span>
                    </div>
                </div>
            </div>
            {{end}}
        </div>
    </div>

    {{if .Result.Schemas}}
    <div class="details">
        <h2>Detailed Differences</h2>

        {{range .Result.Schemas.Missing}}
        <div class="schema-section">
            <h3>Schema: {{.Name}} <span class="badge missing">MISSING</span></h3>
        </div>
        {{end}}

        {{range .Result.Schemas.Extra}}
        <div class="schema-section">
            <h3>Schema: {{.Name}} <span class="badge extra">EXTRA</span></h3>
        </div>
        {{end}}

        {{range .Result.Schemas.Modified}}
        <div class="schema-section">
            <h3>Schema: {{.Name}} <span class="badge modified">MODIFIED</span></h3>

            {{if .Tables}}
                {{if .Tables.Missing}}
                <h4>Missing Tables</h4>
                <ul class="item-list">
                    {{range .Tables.Missing}}
                    <li class="missing">{{.Name}}</li>
                    {{end}}
                </ul>
                {{end}}

                {{if .Tables.Extra}}
                <h4>Extra Tables</h4>
                <ul class="item-list">
                    {{range .Tables.Extra}}
                    <li class="extra">{{.Name}}</li>
                    {{end}}
                </ul>
                {{end}}

                {{if .Tables.Modified}}
                <h4>Modified Tables</h4>
                {{range .Tables.Modified}}
                <div class="table-section">
                    <h5>Table: {{.Schema}}.{{.Name}}</h5>

                    {{if .Columns}}
                        {{if .Columns.Missing}}
                        <h6>Missing Columns</h6>
                        <ul class="item-list">
                            {{range .Columns.Missing}}
                            <li class="missing">{{.Name}} ({{.Type}})</li>
                            {{end}}
                        </ul>
                        {{end}}

                        {{if .Columns.Extra}}
                        <h6>Extra Columns</h6>
                        <ul class="item-list">
                            {{range .Columns.Extra}}
                            <li class="extra">{{.Name}} ({{.Type}})</li>
                            {{end}}
                        </ul>
                        {{end}}

                        {{if .Columns.Modified}}
                        <h6>Modified Columns</h6>
                        <ul class="item-list">
                            {{range .Columns.Modified}}
                            <li class="modified">{{.Name}}</li>
                            {{end}}
                        </ul>
                        {{end}}
                    {{end}}

                    {{if .Indexes}}
                        {{if .Indexes.Missing}}
                        <h6>Missing Indexes</h6>
                        <ul class="item-list">
                            {{range .Indexes.Missing}}
                            <li class="missing">{{.Name}}</li>
                            {{end}}
                        </ul>
                        {{end}}

                        {{if .Indexes.Extra}}
                        <h6>Extra Indexes</h6>
                        <ul class="item-list">
                            {{range .Indexes.Extra}}
                            <li class="extra">{{.Name}}</li>
                            {{end}}
                        </ul>
                        {{end}}
                    {{end}}

                    {{if .Constraints}}
                        {{if .Constraints.Missing}}
                        <h6>Missing Constraints</h6>
                        <ul class="item-list">
                            {{range .Constraints.Missing}}
                            <li class="missing">{{.Name}} ({{.Type}})</li>
                            {{end}}
                        </ul>
                        {{end}}

                        {{if .Constraints.Extra}}
                        <h6>Extra Constraints</h6>
                        <ul class="item-list">
                            {{range .Constraints.Extra}}
                            <li class="extra">{{.Name}} ({{.Type}})</li>
                            {{end}}
                        </ul>
                        {{end}}
                    {{end}}
                </div>
                {{end}}
                {{end}}
            {{end}}

            {{if .Sequences}}
                {{if .Sequences.Missing}}
                <h4>Missing Sequences</h4>
                <ul class="item-list">
                    {{range .Sequences.Missing}}
                    <li class="missing">{{.Name}}</li>
                    {{end}}
                </ul>
                {{end}}

                {{if .Sequences.Extra}}
                <h4>Extra Sequences</h4>
                <ul class="item-list">
                    {{range .Sequences.Extra}}
                    <li class="extra">{{.Name}}</li>
                    {{end}}
                </ul>
                {{end}}
            {{end}}

            {{if .Scripts}}
                {{if .Scripts.Missing}}
                <h4>Missing Scripts</h4>
                <ul class="item-list">
                    {{range .Scripts.Missing}}
                    <li class="missing">{{.Name}}</li>
                    {{end}}
                </ul>
                {{end}}

                {{if .Scripts.Extra}}
                <h4>Extra Scripts</h4>
                <ul class="item-list">
                    {{range .Scripts.Extra}}
                    <li class="extra">{{.Name}}</li>
                    {{end}}
                </ul>
                {{end}}

                {{if .Scripts.Modified}}
                <h4>Modified Scripts</h4>
                <ul class="item-list">
                    {{range .Scripts.Modified}}
                    <li class="modified">{{.Name}}</li>
                    {{end}}
                </ul>
                {{end}}
            {{end}}
        </div>
        {{end}}
    </div>
    {{else}}
    <div class="no-diff">
        ✓ No differences found between the databases
    </div>
    {{end}}
</body>
</html>
`
