///|
pub(all) struct PriorWork {
  package_name : String
  version : String
  repository : String
  license : String
  overlap : String
  relation : String
} derive(Eq, Debug)

///|
pub fn PriorWork::PriorWork(
  package_name? : String = "",
  version? : String = "",
  repository? : String = "",
  license? : String = "",
  overlap? : String = "",
  relation? : String = "",
) -> PriorWork {
  { package_name, version, repository, license, overlap, relation }
}

///|
pub(all) struct ExtensionEvidence {
  feature : String
  implementation : String
  proof : String
  value : String
  implemented : Bool
} derive(Eq, Debug)

///|
pub fn ExtensionEvidence::ExtensionEvidence(
  feature? : String = "",
  implementation? : String = "",
  proof? : String = "",
  value? : String = "",
  implemented? : Bool = false,
) -> ExtensionEvidence {
  { feature, implementation, proof, value, implemented }
}

///|
pub(all) struct ReviewFeedback {
  project_title : String
  applicant_package : String
  repository : String
  notice : String
  prior_work : Array[PriorWork]
  relation_statement : String
  extension_evidence : Array[ExtensionEvidence]
  resubmit_deadline : String
} derive(Eq, Debug)

///|
pub fn ReviewFeedback::ReviewFeedback(
  project_title? : String = "",
  applicant_package? : String = "",
  repository? : String = "",
  notice? : String = "",
  prior_work? : Array[PriorWork] = [],
  relation_statement? : String = "",
  extension_evidence? : Array[ExtensionEvidence] = [],
  resubmit_deadline? : String = "",
) -> ReviewFeedback {
  {
    project_title,
    applicant_package,
    repository,
    notice,
    prior_work,
    relation_statement,
    extension_evidence,
    resubmit_deadline,
  }
}

///|
pub(all) struct ReviewFinding {
  id : String
  severity : Severity
  title : String
  detail : String
  action : String
  evidence : String
  penalty : Int
} derive(Eq, Debug)

///|
fn review_finding(
  id : String,
  severity : Severity,
  title : String,
  detail : String,
  action : String,
  evidence : String,
  penalty : Int,
) -> ReviewFinding {
  { id, severity, title, detail, action, evidence, penalty }
}

///|
pub(all) struct ReviewResponse {
  verdict : String
  score : Int
  ready_to_resubmit : Bool
  overlap_risk : String
  prior_count : Int
  implemented_extension_count : Int
  findings : Array[ReviewFinding]
} derive(Eq, Debug)

///|
pub fn review_feedback_response(feedback : ReviewFeedback) -> ReviewResponse {
  let findings = Array::new(capacity=8)
  push_prior_work_findings(findings, feedback)
  push_relation_findings(findings, feedback)
  push_extension_findings(findings, feedback)
  push_resubmit_findings(findings, feedback)
  let mut penalty = 0
  let mut fail_count = 0
  let mut warn_count = 0
  for finding in findings {
    penalty += finding.penalty
    if finding.severity == Fail {
      fail_count += 1
    } else if finding.severity == Warn {
      warn_count += 1
    }
  }
  let score = clamp_score(100 - penalty)
  let implemented = implemented_extension_count(feedback.extension_evidence)
  let ready = fail_count == 0 && score >= 85 && implemented >= 3
  let verdict = if ready { "resubmit-ready" } else { "needs-remediation" }
  let risk = if fail_count > 0 {
    "high"
  } else if warn_count > 0 {
    "controlled"
  } else {
    "low"
  }
  {
    verdict,
    score,
    ready_to_resubmit: ready,
    overlap_risk: risk,
    prior_count: feedback.prior_work.length(),
    implemented_extension_count: implemented,
    findings,
  }
}

///|
pub fn review_feedback_markdown(feedback : ReviewFeedback) -> String {
  review_feedback_response(feedback).to_markdown(feedback)
}

///|
pub fn ReviewResponse::to_markdown(
  self : ReviewResponse,
  feedback : ReviewFeedback,
) -> String {
  let out = StringBuilder()
  out.write_string("# ReviewProof Resubmission Brief\n\n")
  out.write_string("- Project: " + feedback.project_title + "\n")
  out.write_string("- Package: " + feedback.applicant_package + "\n")
  out.write_string("- Repository: " + feedback.repository + "\n")
  out.write_string("- Verdict: " + self.verdict + "\n")
  out.write_string("- Score: " + self.score.to_string() + "/100\n")
  out.write_string("- Overlap risk: " + self.overlap_risk + "\n")
  out.write_string(
    "- Implemented extensions: " +
    self.implemented_extension_count.to_string() +
    "\n\n",
  )
  if feedback.notice != "" {
    out.write_string("## Review Notice\n\n")
    out.write_string(feedback.notice + "\n\n")
  }
  if feedback.prior_work.length() > 0 {
    out.write_string("## Related Prior Work\n\n")
    for prior in feedback.prior_work {
      out.write_string("- " + prior.package_name)
      if prior.version != "" {
        out.write_string("@" + prior.version)
      }
      if prior.license != "" {
        out.write_string(" license=" + prior.license)
      }
      if prior.repository != "" {
        out.write_string(" repo=" + prior.repository)
      }
      if prior.overlap != "" {
        out.write_string(" overlap=" + prior.overlap)
      }
      out.write_string("\n")
    }
    out.write_string("\n")
  }
  if feedback.relation_statement != "" {
    out.write_string("## Relation Statement\n\n")
    out.write_string(feedback.relation_statement + "\n\n")
  }
  out.write_string("## Extension Evidence\n\n")
  for evidence in feedback.extension_evidence {
    let mark = if evidence.implemented { "[implemented]" } else { "[planned]" }
    out.write_string("- " + mark + " " + evidence.feature)
    if evidence.proof != "" {
      out.write_string(" -- " + evidence.proof)
    }
    if evidence.value != "" {
      out.write_string(" Value: " + evidence.value)
    }
    out.write_string("\n")
  }
  out.write_string("\n## Findings\n\n")
  for finding in self.findings {
    out.write_string("- [" + severity_text(finding.severity) + "] ")
    out.write_string(finding.id + ": " + finding.title)
    if finding.evidence != "" {
      out.write_string(" -- " + finding.evidence)
    }
    if finding.action != "" && finding.severity != Pass {
      out.write_string(" Action: " + finding.action)
    }
    out.write_string("\n")
  }
  out.to_string()
}

///|
pub fn example_review_feedback() -> ReviewFeedback {
  ReviewFeedback(
    project_title="ReviewProof: MoonBit review feedback and resubmission proof toolkit",
    applicant_package="WB-ai-nb/reviewproof-kit",
    repository="https://github.com/WB-ai-nb/harborcheck",
    notice="Initial review said the old HarborCheck scope highly overlapped with EJJ-ai-nb/harborcheck@0.1.2 and lacked an extension statement.",
    prior_work=[
      PriorWork(
        package_name="EJJ-ai-nb/harborcheck",
        version="0.1.4",
        repository="https://github.com/EJJ-ai-nb/harborcheck.git",
        license="MIT",
        overlap="README example, provenance and Mooncakes checklist ideas",
        relation="public related prior work, not the new claim of originality",
      ),
    ],
    relation_statement="EJJ-ai-nb/harborcheck is treated as related prior work for the overlapping HarborCheck-style checklist. ReviewProof's resubmission scope is the review-feedback model, overlap disclosure, extension evidence matrix, reviewer-facing correction brief, dossier proof and non-duplication boundary matrix.",
    extension_evidence=[
      ExtensionEvidence(
        feature="Review feedback model",
        implementation="reviewproof.mbt ReviewFeedback and ReviewResponse",
        proof="moon test review feedback cases",
        value="Turns rejection notices into auditable MoonBit data.",
        implemented=true,
      ),
      ExtensionEvidence(
        feature="Prior-work disclosure matrix",
        implementation="PriorWork relation and overlap fields",
        proof="docs/review-response.md",
        value="Names the similar package and separates old overlap from new work.",
        implemented=true,
      ),
      ExtensionEvidence(
        feature="Extension evidence checklist",
        implementation="ExtensionEvidence records",
        proof="review_feedback_markdown output",
        value="Shows concrete new functions, files and tests for resubmission.",
        implemented=true,
      ),
      ExtensionEvidence(
        feature="Reviewer-facing resubmission brief",
        implementation="ReviewResponse::to_markdown",
        proof="cmd/main smoke output",
        value="Generates a concise correction note for the application form.",
        implemented=true,
      ),
      ExtensionEvidence(
        feature="Resubmission evidence dossier",
        implementation="dossier.mbt DossierProfile and DossierReport",
        proof="moon test dossier cases",
        value="Records proof paths, correction timeline and risk closure for reviewers.",
        implemented=true,
      ),
      ExtensionEvidence(
        feature="Non-duplication boundary matrix",
        implementation="boundary.mbt BoundaryMatrix and BoundaryReport",
        proof="moon test boundary cases",
        value="Separates related prior work, auxiliary compatibility and new ReviewProof contributions.",
        implemented=true,
      ),
    ],
    resubmit_deadline="2026-08-24",
  )
}

///|
fn push_prior_work_findings(
  findings : Array[ReviewFinding],
  feedback : ReviewFeedback,
) -> Unit {
  if feedback.prior_work.length() == 0 &&
    contains_any(feedback.notice, ["重叠", "overlap", "duplicate"]) {
    findings.push(
      review_finding(
        "prior-work.missing",
        Fail,
        "Related prior work is disclosed",
        "The review notice mentions overlap but no prior package is recorded.",
        "Add the similar Mooncakes package, version, repository, license and overlap scope.",
        feedback.notice,
        25,
      ),
    )
  } else if feedback.prior_work.length() > 0 {
    findings.push(
      review_finding(
        "prior-work.disclosed",
        Pass,
        "Related prior work is disclosed",
        "",
        "",
        feedback.prior_work.length().to_string() + " prior work records",
        0,
      ),
    )
    for prior in feedback.prior_work {
      if prior.license == "" || prior.repository == "" {
        findings.push(
          review_finding(
            "prior-work.evidence",
            Warn,
            "Prior work has repository and license evidence",
            "A prior work record is missing repository or license evidence.",
            "Fill repository and license fields for " + prior.package_name + ".",
            prior.package_name,
            8,
          ),
        )
      }
    }
  } else {
    findings.push(
      review_finding(
        "prior-work.none",
        Pass,
        "No overlap notice requires prior-work disclosure",
        "",
        "",
        "notice has no overlap signal",
        0,
      ),
    )
  }
}

///|
fn push_relation_findings(
  findings : Array[ReviewFinding],
  feedback : ReviewFeedback,
) -> Unit {
  if feedback.prior_work.length() > 0 && feedback.relation_statement == "" {
    findings.push(
      review_finding(
        "relation.missing",
        Fail,
        "Extension relationship is explained",
        "The application must explain how this work differs from the similar package.",
        "Add a relation statement to README, SUBMISSION and review-response notes.",
        "",
        25,
      ),
    )
    return
  }
  if feedback.prior_work.length() > 0 &&
    !relation_mentions_prior(feedback.relation_statement, feedback.prior_work) {
    findings.push(
      review_finding(
        "relation.names-prior",
        Warn,
        "Relation statement names the similar package",
        "The relationship is described but the prior package is not named explicitly.",
        "Mention the Mooncakes package id in the relation statement.",
        feedback.relation_statement,
        6,
      ),
    )
  } else {
    findings.push(
      review_finding(
        "relation.explained",
        Pass,
        "Extension relationship is explained",
        "",
        "",
        feedback.relation_statement,
        0,
      ),
    )
  }
}

///|
fn push_extension_findings(
  findings : Array[ReviewFinding],
  feedback : ReviewFeedback,
) -> Unit {
  let implemented = implemented_extension_count(feedback.extension_evidence)
  if implemented < 3 {
    findings.push(
      review_finding(
        "extension.insufficient",
        Fail,
        "At least three implemented differentiators are recorded",
        "A resubmission needs concrete implemented differences, not just a renamed package.",
        "Add implemented MoonBit features, tests and documents for the new scope.",
        implemented.to_string() + " implemented extensions",
        30,
      ),
    )
  } else {
    findings.push(
      review_finding(
        "extension.implemented",
        Pass,
        "At least three implemented differentiators are recorded",
        "",
        "",
        implemented.to_string() + " implemented extensions",
        0,
      ),
    )
  }
  for evidence in feedback.extension_evidence {
    if evidence.implemented &&
      (evidence.implementation == "" || evidence.proof == "") {
      findings.push(
        review_finding(
          "extension.proof",
          Warn,
          "Implemented differentiators have proof files",
          "An implemented extension should point to code, tests or documentation.",
          "Fill implementation and proof for " + evidence.feature + ".",
          evidence.feature,
          5,
        ),
      )
    }
  }
}

///|
fn push_resubmit_findings(
  findings : Array[ReviewFinding],
  feedback : ReviewFeedback,
) -> Unit {
  if feedback.project_title == "" || feedback.applicant_package == "" {
    findings.push(
      review_finding(
        "submission.identity",
        Fail,
        "Resubmission title and package are explicit",
        "Reviewers need a concrete project title and package id.",
        "Fill project_title and applicant_package.",
        feedback.project_title + " " + feedback.applicant_package,
        15,
      ),
    )
  } else {
    findings.push(
      review_finding(
        "submission.identity",
        Pass,
        "Resubmission title and package are explicit",
        "",
        "",
        feedback.project_title + " / " + feedback.applicant_package,
        0,
      ),
    )
  }
  if feedback.resubmit_deadline == "" {
    findings.push(
      review_finding(
        "submission.deadline",
        Warn,
        "Resubmission deadline is recorded",
        "A deadline helps keep the correction material time-bound.",
        "Record the official resubmission deadline.",
        "",
        3,
      ),
    )
  }
}

///|
fn implemented_extension_count(evidence : Array[ExtensionEvidence]) -> Int {
  let mut count = 0
  for item in evidence {
    if item.implemented {
      count += 1
    }
  }
  count
}

///|
fn relation_mentions_prior(
  relation : String,
  prior_work : Array[PriorWork],
) -> Bool {
  for prior in prior_work {
    if prior.package_name != "" && contains_ci(relation, prior.package_name) {
      return true
    }
  }
  false
}

///|
fn clamp_score(score : Int) -> Int {
  if score < 0 {
    0
  } else if score > 100 {
    100
  } else {
    score
  }
}