///|
pub fn profile_startup() -> MailSecurityProfile {
  {
    name: "startup",
    minimum_score: 70,
    require_spf_hardfail: false,
    require_dmarc_enforcement: false,
    require_dkim: false,
    require_mtasts: false,
    require_tlsrpt: false,
    require_bimi: false,
    allow_testing_modes: true,
  }
}

///|
pub fn profile_monitoring() -> MailSecurityProfile {
  {
    name: "monitoring",
    minimum_score: 80,
    require_spf_hardfail: false,
    require_dmarc_enforcement: false,
    require_dkim: true,
    require_mtasts: false,
    require_tlsrpt: true,
    require_bimi: false,
    allow_testing_modes: true,
  }
}

///|
pub fn profile_production() -> MailSecurityProfile {
  {
    name: "production",
    minimum_score: 90,
    require_spf_hardfail: true,
    require_dmarc_enforcement: true,
    require_dkim: true,
    require_mtasts: true,
    require_tlsrpt: true,
    require_bimi: false,
    allow_testing_modes: false,
  }
}

///|
pub fn profile_brand() -> MailSecurityProfile {
  {
    name: "brand",
    minimum_score: 94,
    require_spf_hardfail: true,
    require_dmarc_enforcement: true,
    require_dkim: true,
    require_mtasts: true,
    require_tlsrpt: true,
    require_bimi: true,
    allow_testing_modes: false,
  }
}

///|
pub fn assess_profile(
  report : MailSecuritySuiteReport,
  profile : MailSecurityProfile,
) -> ProfileAssessment {
  let failures = Array::new()
  let findings = Array::new(capacity=12)
  if report.score >= profile.minimum_score {
    findings.push(
      pass(
        "profile.score",
        "Suite score meets profile minimum",
        report.score.to_string() + "/" + profile.minimum_score.to_string(),
      ),
    )
  } else {
    failures.push("score")
    findings.push(
      fail(
        "profile.score-low",
        "Suite score is below profile minimum",
        "The selected profile requires a higher score.",
        report.score.to_string() + "/" + profile.minimum_score.to_string(),
        "Resolve high-priority action items and rerun the assessment.",
      ),
    )
  }
  assess_spf_requirement(report, profile, failures, findings)
  assess_dmarc_requirement(report, profile, failures, findings)
  assess_dkim_requirement(report, profile, failures, findings)
  assess_transport_requirement(report, profile, failures, findings)
  assess_bimi_requirement(report, profile, failures, findings)
  assess_testing_requirement(report, profile, failures, findings)
  {
    profile_name: profile.name,
    passed: failures.length() == 0,
    score: report.score,
    missing_count: failures.length(),
    failed_requirements: failures,
    findings,
  }
}

///|
fn assess_spf_requirement(
  report : MailSecuritySuiteReport,
  profile : MailSecurityProfile,
  failures : Array[String],
  findings : Array[PolicyFinding],
) -> Unit {
  if !profile.require_spf_hardfail {
    findings.push(
      pass(
        "profile.spf-optional",
        "SPF hardfail is optional for this profile",
        profile.name,
      ),
    )
    return
  }
  if report.spf.valid_version && report.spf.all_qualifier == "-" {
    findings.push(
      pass("profile.spf-hardfail", "SPF hardfail requirement is met", "-all"),
    )
  } else {
    failures.push("spf-hardfail")
    findings.push(
      fail(
        "profile.spf-hardfail-missing",
        "SPF hardfail requirement is not met",
        "Production profiles expect SPF to end with -all or equivalent strict delegation.",
        report.spf.all_qualifier,
        "Change SPF terminal policy to -all after all senders are listed.",
      ),
    )
  }
}

///|
fn assess_dmarc_requirement(
  report : MailSecuritySuiteReport,
  profile : MailSecurityProfile,
  failures : Array[String],
  findings : Array[PolicyFinding],
) -> Unit {
  if !profile.require_dmarc_enforcement {
    findings.push(
      pass(
        "profile.dmarc-optional",
        "DMARC enforcement is optional for this profile",
        profile.name,
      ),
    )
    return
  }
  if report.dmarc.policy == "reject" || report.dmarc.policy == "quarantine" {
    findings.push(
      pass(
        "profile.dmarc-enforcement",
        "DMARC enforcement requirement is met",
        report.dmarc.policy,
      ),
    )
  } else {
    failures.push("dmarc-enforcement")
    findings.push(
      fail(
        "profile.dmarc-enforcement-missing",
        "DMARC enforcement requirement is not met",
        "Production profiles expect p=quarantine or p=reject.",
        report.dmarc.policy,
        "Move DMARC from monitoring to quarantine or reject after alignment review.",
      ),
    )
  }
}

///|
fn assess_dkim_requirement(
  report : MailSecuritySuiteReport,
  profile : MailSecurityProfile,
  failures : Array[String],
  findings : Array[PolicyFinding],
) -> Unit {
  if !profile.require_dkim {
    findings.push(
      pass(
        "profile.dkim-optional",
        "DKIM is optional for this profile",
        profile.name,
      ),
    )
    return
  }
  if report.dkim.is_configured() {
    findings.push(
      pass(
        "profile.dkim",
        "DKIM requirement is met",
        report.dkim.key_strength_label(),
      ),
    )
  } else {
    failures.push("dkim")
    findings.push(
      fail(
        "profile.dkim-missing", "DKIM requirement is not met", "This profile expects at least one usable DKIM selector record.",
        "", "Publish a DKIM selector record and rotate senders to sign mail.",
      ),
    )
  }
}

///|
fn assess_transport_requirement(
  report : MailSecuritySuiteReport,
  profile : MailSecurityProfile,
  failures : Array[String],
  findings : Array[PolicyFinding],
) -> Unit {
  if profile.require_mtasts {
    if report.mtasts.is_enforcing() {
      findings.push(
        pass(
          "profile.mtasts",
          "MTA-STS enforcement requirement is met",
          report.mtasts.mode,
        ),
      )
    } else {
      failures.push("mtasts")
      findings.push(
        fail(
          "profile.mtasts-missing",
          "MTA-STS enforcement requirement is not met",
          "This profile expects mode: enforce.",
          report.mtasts.mode,
          "Publish and verify an MTA-STS policy in enforce mode.",
        ),
      )
    }
  } else {
    findings.push(
      pass(
        "profile.mtasts-optional",
        "MTA-STS enforcement is optional for this profile",
        profile.name,
      ),
    )
  }
  if profile.require_tlsrpt {
    if report.tlsrpt.is_configured() {
      findings.push(
        pass(
          "profile.tlsrpt",
          "TLS-RPT requirement is met",
          report.tlsrpt.rua_count.to_string(),
        ),
      )
    } else {
      failures.push("tlsrpt")
      findings.push(
        fail(
          "profile.tlsrpt-missing", "TLS-RPT requirement is not met", "This profile expects TLS delivery reports.",
          "", "Publish a TLS-RPT record with at least one rua destination.",
        ),
      )
    }
  } else {
    findings.push(
      pass(
        "profile.tlsrpt-optional",
        "TLS-RPT is optional for this profile",
        profile.name,
      ),
    )
  }
}

///|
fn assess_bimi_requirement(
  report : MailSecuritySuiteReport,
  profile : MailSecurityProfile,
  failures : Array[String],
  findings : Array[PolicyFinding],
) -> Unit {
  if !profile.require_bimi {
    findings.push(
      pass(
        "profile.bimi-optional",
        "BIMI is optional for this profile",
        profile.name,
      ),
    )
    return
  }
  if report.bimi.is_configured() && report.bimi.has_https_logo() {
    findings.push(
      pass("profile.bimi", "BIMI requirement is met", report.bimi.logo_url),
    )
  } else {
    failures.push("bimi")
    findings.push(
      fail(
        "profile.bimi-missing", "BIMI requirement is not met", "Brand profile expects a valid BIMI logo record.",
        "", "Publish v=BIMI1 with an HTTPS SVG logo URL.",
      ),
    )
  }
}

///|
fn assess_testing_requirement(
  report : MailSecuritySuiteReport,
  profile : MailSecurityProfile,
  failures : Array[String],
  findings : Array[PolicyFinding],
) -> Unit {
  if profile.allow_testing_modes {
    findings.push(
      pass(
        "profile.testing-allowed",
        "Testing modes are allowed for this profile",
        profile.name,
      ),
    )
    return
  }
  if report.dkim.is_testing() || report.mtasts.is_testing() {
    failures.push("testing-mode")
    findings.push(
      fail(
        "profile.testing-mode", "Testing mode is not allowed for this profile", "Production-oriented profiles should not leave DKIM or MTA-STS in testing mode.",
        "", "Remove DKIM t=y and move MTA-STS mode to enforce.",
      ),
    )
  } else {
    findings.push(
      pass(
        "profile.testing-mode",
        "No disallowed testing modes were detected",
        profile.name,
      ),
    )
  }
}

///|
pub fn ProfileAssessment::to_markdown(self : ProfileAssessment) -> String {
  let out = StringBuilder()
  out.write_string("# MailShield Profile Assessment\n\n")
  out.write_string("- Profile: ")
  out.write_string(self.profile_name)
  out.write_string("\n")
  out.write_string("- Passed: ")
  out.write_string(bool_text(self.passed))
  out.write_string("\n")
  out.write_string("- Score: ")
  out.write_string(self.score.to_string())
  out.write_string("\n")
  out.write_string("- Missing requirements: ")
  out.write_string(self.missing_count.to_string())
  out.write_string("\n\n")
  out.write_string("## Failed Requirements\n\n")
  if self.failed_requirements.length() == 0 {
    out.write_string("- None\n")
  } else {
    for requirement in self.failed_requirements {
      out.write_string("- ")
      out.write_string(requirement)
      out.write_string("\n")
    }
  }
  out.write_string("\n## Findings\n\n")
  for finding in self.findings {
    out.write_string("- [")
    out.write_string(severity_text(finding.severity))
    out.write_string("] ")
    out.write_string(finding.id)
    out.write_string(": ")
    out.write_string(finding.title)
    if !finding.evidence.is_empty() {
      out.write_string(" -- ")
      out.write_string(finding.evidence)
    }
    out.write_string("\n")
  }
  out.to_string()
}

///|
pub fn ProfileAssessment::to_json(self : ProfileAssessment) -> String {
  let out = StringBuilder()
  out.write_string("{")
  append_json_string(out, "profile", self.profile_name)
  out.write_string(",")
  append_json_bool(out, "passed", self.passed)
  out.write_string(",")
  append_json_int(out, "score", self.score)
  out.write_string(",")
  append_json_int(out, "missing_count", self.missing_count)
  out.write_string(",\"failed_requirements\":[")
  for i in 0.. 0 {
      out.write_string(",")
    }
    out.write_string("\"")
    out.write_string(json_escape(self.failed_requirements[i]))
    out.write_string("\"")
  }
  out.write_string("]}")
  out.to_string()
}

///|
pub fn recommended_profile(report : MailSecuritySuiteReport) -> String {
  let startup = assess_profile(report, profile_startup())
  let monitoring = assess_profile(report, profile_monitoring())
  let production = assess_profile(report, profile_production())
  let brand = assess_profile(report, profile_brand())
  if brand.passed {
    "brand"
  } else if production.passed {
    "production"
  } else if monitoring.passed {
    "monitoring"
  } else if startup.passed {
    "startup"
  } else {
    "below-startup"
  }
}

///|
pub fn profile_name_list() -> Array[String] {
  let names = Array::new(capacity=4)
  names.push("startup")
  names.push("monitoring")
  names.push("production")
  names.push("brand")
  names
}