package cli

import (
	"fmt"

	"github.com/spf13/cobra"
)

const trafficAnalysisSchemaJSON = `{
  "$schema": "https://json-schema.org/draft/2020-12/schema",
  "$id": "https://github.com/mvanhorn/cli-printing-press/schemas/traffic-analysis.schema.json",
  "title": "CLI Printing Press traffic-analysis.json",
  "type": "object",
  "additionalProperties": false,
  "required": ["version", "summary", "protocols", "auth", "endpoint_clusters"],
  "properties": {
    "version": {"type": "string"},
    "summary": {
      "type": "object",
      "additionalProperties": false,
      "required": ["entry_count", "api_entry_count", "noise_entry_count"],
      "properties": {
        "target_url": {"type": "string"},
        "captured_at": {"type": "string"},
        "entry_count": {"type": "integer", "minimum": 0},
        "api_entry_count": {"type": "integer", "minimum": 0},
        "noise_entry_count": {"type": "integer", "minimum": 0},
        "host_distribution": {"type": "object", "additionalProperties": {"type": "integer", "minimum": 0}},
        "time_start": {"type": "string"},
        "time_end": {"type": "string"}
      }
    },
    "reachability": {
      "type": "object",
      "additionalProperties": false,
      "required": ["mode", "confidence"],
      "properties": {
        "mode": {"type": "string", "enum": ["standard_http", "browser_http", "browser_clearance_http", "browser_required", "blocked", "unknown"]},
        "confidence": {"type": "number", "minimum": 0, "maximum": 1},
        "reasons": {"type": "array", "items": {"type": "string"}},
        "evidence": {"type": "array", "items": {"oneOf": [{"$ref": "#/$defs/evidence_ref"}, {"type": "string"}]}},
        "impersonation_safe": {"type": "boolean"}
      }
    },
    "protocols": {"type": "array", "items": {"$ref": "#/$defs/protocol_observation"}},
    "auth": {
      "type": "object",
      "additionalProperties": false,
      "properties": {
        "candidates": {"type": "array", "items": {"$ref": "#/$defs/auth_candidate"}},
        "captcha_preflight": {"type": "boolean"}
      }
    },
    "protections": {"type": "array", "items": {"$ref": "#/$defs/protection_observation"}},
    "secondary_hosts": {"type": "array", "items": {"$ref": "#/$defs/secondary_host"}},
    "endpoint_clusters": {"type": "array", "items": {"$ref": "#/$defs/endpoint_cluster"}},
    "request_sequences": {"type": "array", "items": {"$ref": "#/$defs/request_sequence"}},
    "pagination": {"type": "array", "items": {"$ref": "#/$defs/pagination_signal"}},
    "candidate_commands": {"type": "array", "items": {"$ref": "#/$defs/candidate_command"}},
    "generation_hints": {"type": "array", "items": {"type": "string"}},
    "warnings": {"type": "array", "items": {"$ref": "#/$defs/analysis_warning"}}
  },
  "$defs": {
    "evidence_ref": {
      "type": "object",
      "additionalProperties": false,
      "required": ["entry_index"],
      "properties": {
        "entry_index": {"type": "integer", "minimum": 0},
        "method": {"type": "string"},
        "host": {"type": "string"},
        "path": {"type": "string"},
        "status": {"type": "integer"},
        "content_type": {"type": "string"},
        "reason": {"type": "string"}
      }
    },
    "protocol_observation": {
      "type": "object",
      "additionalProperties": false,
      "required": ["label", "confidence"],
      "properties": {
        "label": {"type": "string"},
        "confidence": {"type": "number", "minimum": 0, "maximum": 1},
        "evidence": {"type": "array", "items": {"oneOf": [{"$ref": "#/$defs/evidence_ref"}, {"type": "string"}]}},
        "details": {"type": "object", "additionalProperties": {"type": "string"}}
      }
    },
    "auth_candidate": {
      "type": "object",
      "additionalProperties": false,
      "required": ["type", "confidence"],
      "properties": {
        "type": {"type": "string"},
        "confidence": {"type": "number", "minimum": 0, "maximum": 1},
        "header_names": {"type": "array", "items": {"type": "string"}},
        "query_names": {"type": "array", "items": {"type": "string"}},
        "cookie_names": {"type": "array", "items": {"type": "string"}},
        "domain_hints": {"type": "array", "items": {"type": "string"}},
        "evidence": {"type": "array", "items": {"$ref": "#/$defs/evidence_ref"}}
      }
    },
    "protection_observation": {
      "type": "object",
      "additionalProperties": false,
      "required": ["label", "confidence"],
      "properties": {
        "label": {"type": "string"},
        "confidence": {"type": "number", "minimum": 0, "maximum": 1},
        "evidence": {"type": "array", "items": {"oneOf": [{"$ref": "#/$defs/evidence_ref"}, {"type": "string"}]}},
        "notes": {"type": "array", "items": {"type": "string"}}
      }
    },
    "secondary_host": {
      "type": "object",
      "additionalProperties": false,
      "required": ["host", "count", "reason"],
      "properties": {
        "host": {"type": "string"},
        "count": {"type": "integer", "minimum": 0},
        "reason": {"type": "string", "enum": ["non-primary host", "telemetry host"]}
      }
    },
    "endpoint_cluster": {
      "type": "object",
      "additionalProperties": false,
      "required": ["method", "path", "count"],
      "properties": {
        "host": {"type": "string"},
        "method": {"type": "string"},
        "path": {"type": "string"},
        "count": {"type": "integer", "minimum": 0},
        "statuses": {"type": "array", "items": {"type": "integer"}},
        "content_types": {"type": "array", "items": {"type": "string"}},
        "size_class": {"type": "string"},
        "request_shape": {"$ref": "#/$defs/shape_summary"},
        "response_shape": {"$ref": "#/$defs/shape_summary"},
        "evidence": {"type": "array", "items": {"$ref": "#/$defs/evidence_ref"}}
      }
    },
    "shape_summary": {
      "type": "object",
      "additionalProperties": false,
      "properties": {
        "kind": {"type": "string"},
        "fields": {"type": "array", "items": {"$ref": "#/$defs/shape_field"}}
      }
    },
    "shape_field": {
      "type": "object",
      "additionalProperties": false,
      "required": ["name"],
      "properties": {
        "name": {"type": "string"},
        "type": {"type": "string"},
        "required": {"type": "boolean"},
        "format": {"type": "string"}
      }
    },
    "request_sequence": {
      "type": "object",
      "additionalProperties": false,
      "required": ["label", "confidence"],
      "properties": {
        "label": {"type": "string"},
        "confidence": {"type": "number", "minimum": 0, "maximum": 1},
        "evidence": {"type": "array", "items": {"oneOf": [{"$ref": "#/$defs/evidence_ref"}, {"type": "string"}]}},
        "notes": {"type": "array", "items": {"type": "string"}}
      }
    },
    "pagination_signal": {
      "type": "object",
      "additionalProperties": false,
      "required": ["location", "name", "confidence"],
      "properties": {
        "location": {"type": "string"},
        "name": {"type": "string"},
        "confidence": {"type": "number", "minimum": 0, "maximum": 1},
        "evidence": {"type": "array", "items": {"$ref": "#/$defs/evidence_ref"}}
      }
    },
    "candidate_command": {
      "type": "object",
      "additionalProperties": false,
      "required": ["name", "confidence"],
      "properties": {
        "name": {"type": "string"},
        "resource": {"type": "string"},
        "confidence": {"type": "number", "minimum": 0, "maximum": 1},
        "rationale": {"type": "string"},
        "evidence": {"type": "array", "items": {"$ref": "#/$defs/evidence_ref"}}
      }
    },
    "analysis_warning": {
      "type": "object",
      "additionalProperties": false,
      "required": ["type", "message", "confidence"],
      "properties": {
        "type": {"type": "string"},
        "message": {"type": "string"},
        "confidence": {"type": "number", "minimum": 0, "maximum": 1},
        "evidence": {"type": "array", "items": {"$ref": "#/$defs/evidence_ref"}}
      }
    }
  }
}`

const phase5MarkerSchemaJSON = `{
  "$schema": "https://json-schema.org/draft/2020-12/schema",
  "$id": "https://github.com/mvanhorn/cli-printing-press/schemas/phase5-acceptance.schema.json",
  "title": "CLI Printing Press phase5-acceptance.json",
  "type": "object",
  "additionalProperties": false,
  "required": ["schema_version", "api_name", "run_id", "status", "level", "matrix_size"],
  "properties": {
    "schema_version": {"type": "integer", "const": 1},
    "api_name": {"type": "string", "minLength": 1},
    "cli_name": {"type": "string"},
    "run_id": {"type": "string", "minLength": 1},
    "status": {"type": "string", "enum": ["pass", "fail"]},
    "level": {"type": "string", "enum": ["quick", "full"]},
    "matrix_size": {"type": "integer", "minimum": 1},
    "tests_total": {"type": "integer", "minimum": 0},
    "tests_passed": {"type": "integer", "minimum": 0},
    "tests_skipped": {"type": "integer", "minimum": 0},
    "tests_failed": {"type": "integer", "minimum": 0},
    "completed_at": {"type": "string", "format": "date-time"},
    "summary": {"type": "string"},
    "auth_context": {"$ref": "#/$defs/auth_context"},
    "failure_summary": {"$ref": "#/$defs/failure_summary"}
  },
  "allOf": [
    {
      "if": {"properties": {"status": {"const": "pass"}}, "required": ["status"]},
      "then": {"required": ["tests_passed"], "properties": {"tests_passed": {"minimum": 1}}}
    }
  ],
  "$defs": {
    "auth_context": {
      "type": "object",
      "additionalProperties": false,
      "properties": {
        "type": {"type": "string"},
        "api_key_available": {"type": "boolean"},
        "browser_session_available": {"type": "boolean"},
        "local_sqlite": {"type": "boolean"}
      }
    },
    "failure_summary": {
      "type": "object",
      "additionalProperties": false,
      "properties": {
        "transport_error": {"type": "integer", "minimum": 0},
        "http_4xx": {"type": "integer", "minimum": 0},
        "http_5xx": {"type": "integer", "minimum": 0},
        "exit_nonzero": {"type": "integer", "minimum": 0},
        "output_mismatch": {"type": "integer", "minimum": 0},
        "other": {"type": "integer", "minimum": 0},
        "commands": {"type": "array", "items": {"type": "string"}}
      }
    }
  }
}`

const phase5SkipSchemaJSON = `{
  "$schema": "https://json-schema.org/draft/2020-12/schema",
  "$id": "https://github.com/mvanhorn/cli-printing-press/schemas/phase5-skip.schema.json",
  "title": "CLI Printing Press phase5-skip.json",
  "type": "object",
  "additionalProperties": false,
  "required": ["schema_version", "api_name", "run_id", "status", "skip_reason"],
  "properties": {
    "schema_version": {"type": "integer", "const": 1},
    "api_name": {"type": "string", "minLength": 1},
    "cli_name": {"type": "string"},
    "run_id": {"type": "string", "minLength": 1},
    "status": {"type": "string", "const": "skip"},
    "skip_reason": {"type": "string", "minLength": 1},
    "auth_context": {"$ref": "#/$defs/auth_context"}
  },
  "$defs": {
    "auth_context": {
      "type": "object",
      "additionalProperties": false,
      "properties": {
        "type": {"type": "string"},
        "api_key_available": {"type": "boolean"},
        "browser_session_available": {"type": "boolean"},
        "local_sqlite": {"type": "boolean"},
        "local_network_only": {"type": "boolean"}
      }
    }
  }
}`

func newSchemaCmd() *cobra.Command {
	cmd := &cobra.Command{
		Use:   "schema",
		Short: "Print machine-readable schemas for Printing Press artifacts",
	}
	cmd.AddCommand(newSchemaPrintCmd("traffic-analysis", "Print the traffic-analysis.json schema", trafficAnalysisSchemaJSON))
	cmd.AddCommand(newSchemaPrintCmd("phase5-marker", "Print the phase5-acceptance.json schema", phase5MarkerSchemaJSON))
	cmd.AddCommand(newSchemaPrintCmd("phase5-skip", "Print the phase5-skip.json schema", phase5SkipSchemaJSON))
	return cmd
}

func newSchemaPrintCmd(use, short, schema string) *cobra.Command {
	var asJSON bool
	cmd := &cobra.Command{
		Use:   use,
		Short: short,
		RunE: func(cmd *cobra.Command, args []string) error {
			fmt.Fprintln(cmd.OutOrStdout(), schema)
			return nil
		},
	}
	cmd.Flags().BoolVar(&asJSON, "json", false, "Emit JSON schema (default; accepted for command symmetry)")
	return cmd
}
