# ============================================================
# KYC/AML Compliance SPARQL Query Templates
# Version: 1.0.0
# ============================================================

PREFIX kyc: <http://example.org/kyc-aml#>
PREFIX rdf: <http://www.w3.org/1999/02/22-rdf-syntax-ns#>
PREFIX rdfs: <http://www.w3.org/2000/01/rdf-schema#>
PREFIX xsd: <http://www.w3.org/2001/XMLSchema#>

# ============================================================
# Query 1: Extract Customer Identity Documents
# ============================================================
SELECT ?customerID ?fullName ?docType ?docNumber ?issuer ?expiryDate ?verified
WHERE {
  ?customer kyc:customerID ?customerID ;
            kyc:fullName ?fullName ;
            kyc:hasIdentityDocument ?doc ;
            kyc:hasVerification ?verification .

  ?doc a ?docClass ;
       kyc:documentNumber ?docNumber ;
       kyc:documentIssuer ?issuer ;
       kyc:documentExpiryDate ?expiryDate .

  ?docClass rdfs:subClassOf* kyc:IdentityDocument .
  BIND(STRAFTER(STR(?docClass), "#") AS ?docType)

  ?verification kyc:verificationStatus ?verified .
}

# ============================================================
# Query 2: Calculate Customer Risk Score
# ============================================================
CONSTRUCT {
  ?customer kyc:hasRiskAssessment ?assessment .

  ?assessment a kyc:RiskAssessment ;
              kyc:hasRiskScore ?score ;
              kyc:hasRiskLevel ?level ;
              kyc:assessmentDate ?assessmentDate ;
              kyc:hasRiskFactor ?geoFactor ;
              kyc:hasRiskFactor ?txFactor ;
              kyc:hasRiskFactor ?pepFactor .

  ?score a kyc:RiskScore ;
         kyc:scoreValue ?scoreValue ;
         kyc:scoreReason ?reason .

  ?level a ?levelClass .

  ?geoFactor a kyc:GeographicRisk .
  ?txFactor a kyc:TransactionRisk .
  ?pepFactor a kyc:PEPRisk .
}
WHERE {
  ?customer kyc:customerID ?customerID ;
            kyc:countryOfResidence ?country .

  BIND(NOW() AS ?assessmentDate)

  # Calculate risk score based on factors (simplified)
  BIND(
    IF(?country IN ("AF", "BY", "CD", "CU", "IR", "IQ", "LB", "LY", "MM", "KP", "SO", "SD", "SY", "VE", "YE", "ZW"), 30,
    IF(?country IN ("AL", "BS", "BW", "GH", "JM", "MU", "PA", "RS", "TT", "VU", "ZW"), 20,
    10)) AS ?geoScore
  )

  BIND(?geoScore AS ?scoreValue)

  BIND(
    IF(?scoreValue >= 50, kyc:HighRisk,
    IF(?scoreValue >= 25, kyc:MediumRisk,
    kyc:LowRisk)) AS ?levelClass
  )

  BIND(CONCAT("Geographic risk: ", STR(?geoScore)) AS ?reason)
}

# ============================================================
# Query 3: Sanctions List Matching
# ============================================================
SELECT ?customerID ?customerName ?matchedName ?listType ?matchScore ?matchReason
WHERE {
  ?customer kyc:customerID ?customerID ;
            kyc:fullName ?customerName ;
            kyc:hasSanctionsScreening ?screening .

  ?screening kyc:hasSanctionsMatch ?match .

  ?match kyc:matchScore ?matchScore ;
         kyc:matchReason ?matchReason ;
         kyc:matchesList ?list .

  ?list a ?listClass .
  ?listClass rdfs:subClassOf* kyc:SanctionsList .
  BIND(STRAFTER(STR(?listClass), "#") AS ?listType)

  # Extract matched name from match reason
  BIND(?customerName AS ?matchedName)

  FILTER(?matchScore > 0.8)
}
ORDER BY DESC(?matchScore)

# ============================================================
# Query 4: Generate Suspicious Activity Report (SAR)
# ============================================================
CONSTRUCT {
  ?sar a kyc:SAR ;
       kyc:sarID ?sarID ;
       kyc:hasReportableActivity ?activity ;
       kyc:narrativeDescription ?narrative ;
       kyc:hasSARFiling ?filing .

  ?activity a ?activityType .

  ?filing a kyc:SARFiling ;
          kyc:sarFilingDate ?filingDate ;
          kyc:filingAuthority ?authority .

  ?customer kyc:hasSAR ?sar .
}
WHERE {
  ?customer kyc:customerID ?customerID ;
            kyc:fullName ?customerName .

  ?alert a kyc:TruePositive ;
         kyc:alertID ?alertID ;
         kyc:alertSeverity "HIGH" .

  BIND(CONCAT("SAR-", ?customerID, "-", SUBSTR(STR(?alertID), 1, 8)) AS ?sarID)
  BIND(NOW() AS ?filingDate)
  BIND("FinCEN" AS ?authority)
  BIND(kyc:MoneyLaundering AS ?activityType)
  BIND(CONCAT("Customer ", ?customerName, " (ID: ", ?customerID, ") engaged in suspicious transaction patterns consistent with potential money laundering. Multiple high-value transactions to high-risk jurisdictions detected.") AS ?narrative)
}

# ============================================================
# Query 5: Find High-Risk Customers Requiring EDD
# ============================================================
SELECT ?customerID ?fullName ?riskLevel ?riskScore ?countryOfResidence ?isPEP
WHERE {
  ?customer kyc:customerID ?customerID ;
            kyc:fullName ?fullName ;
            kyc:countryOfResidence ?countryOfResidence ;
            kyc:hasRiskAssessment ?assessment .

  ?assessment kyc:hasRiskLevel ?level ;
              kyc:hasRiskScore ?scoreObj .

  ?level a kyc:HighRisk .
  BIND("HIGH" AS ?riskLevel)

  ?scoreObj kyc:scoreValue ?riskScore .

  OPTIONAL {
    ?customer kyc:isPEP ?pepObj .
    BIND(true AS ?isPEP)
  }

  BIND(IF(BOUND(?pepObj), true, false) AS ?isPEP)
}
ORDER BY DESC(?riskScore)

# ============================================================
# Query 6: PEP Screening Results
# ============================================================
SELECT ?customerID ?fullName ?pepType ?pepRole ?pepJurisdiction
WHERE {
  ?customer kyc:customerID ?customerID ;
            kyc:fullName ?fullName ;
            kyc:isPEP ?pep .

  ?pep a ?pepClass ;
       kyc:pepRole ?pepRole ;
       kyc:pepJurisdiction ?pepJurisdiction .

  ?pepClass rdfs:subClassOf* kyc:PEP .
  BIND(STRAFTER(STR(?pepClass), "#") AS ?pepType)
}

# ============================================================
# Query 7: Transaction Monitoring Alerts
# ============================================================
SELECT ?alertID ?customerID ?alertDate ?severity ?status ?ruleName ?description
WHERE {
  ?alert kyc:alertID ?alertID ;
         kyc:alertDate ?alertDate ;
         kyc:alertSeverity ?severity ;
         kyc:alertStatus ?status ;
         kyc:triggeredByRule ?rule .

  ?rule a ?ruleClass ;
        kyc:ruleName ?ruleName ;
        kyc:ruleDescription ?description .

  ?monitoring kyc:hasAlert ?alert ;
              kyc:monitoringCustomer ?customer .

  ?customer kyc:customerID ?customerID .

  FILTER(?status IN ("OPEN", "INVESTIGATING"))
}
ORDER BY DESC(?alertDate) DESC(?severity)

# ============================================================
# Query 8: Find Customers Due for Periodic Review
# ============================================================
SELECT ?customerID ?fullName ?lastReviewDate ?nextReviewDate ?daysOverdue
WHERE {
  ?customer kyc:customerID ?customerID ;
            kyc:fullName ?fullName ;
            kyc:hasDueDiligence ?dd .

  ?dd a kyc:PeriodicReview ;
      kyc:reviewDate ?lastReviewDate ;
      kyc:nextReviewDate ?nextReviewDate .

  BIND(xsd:integer((CURRENT_DATE() - ?nextReviewDate) / "P1D"^^xsd:duration) AS ?daysOverdue)

  FILTER(?nextReviewDate <= CURRENT_DATE())
}
ORDER BY DESC(?daysOverdue)

# ============================================================
# Query 9: Compliance Audit Trail
# ============================================================
SELECT ?customerID ?eventType ?eventDate ?performedBy ?details
WHERE {
  ?customer kyc:customerID ?customerID .

  {
    ?customer kyc:hasVerification ?event .
    ?event kyc:verificationDate ?eventDate .
    BIND("IDENTITY_VERIFICATION" AS ?eventType)
  }
  UNION
  {
    ?customer kyc:hasRiskAssessment ?event .
    ?event kyc:assessmentDate ?eventDate .
    BIND("RISK_ASSESSMENT" AS ?eventType)
  }
  UNION
  {
    ?customer kyc:hasSanctionsScreening ?event .
    ?event kyc:screeningDate ?eventDate .
    BIND("SANCTIONS_SCREENING" AS ?eventType)
  }

  OPTIONAL {
    ?event kyc:performedBy ?performedBy .
  }

  BIND("System automated process" AS ?performedBy)
}
ORDER BY DESC(?eventDate)

# ============================================================
# Query 10: Regulatory Reporting Summary
# ============================================================
SELECT ?reportingPeriod (COUNT(DISTINCT ?customer) AS ?totalCustomers)
       (COUNT(DISTINCT ?highRisk) AS ?highRiskCustomers)
       (COUNT(DISTINCT ?sar) AS ?totalSARs)
       (COUNT(DISTINCT ?alert) AS ?totalAlerts)
WHERE {
  BIND("2025-Q1" AS ?reportingPeriod)

  ?customer a kyc:Customer .

  OPTIONAL {
    ?customer kyc:hasRiskAssessment ?assessment .
    ?assessment kyc:hasRiskLevel ?level .
    ?level a kyc:HighRisk .
    BIND(?customer AS ?highRisk)
  }

  OPTIONAL {
    ?customer kyc:hasSAR ?sarObj .
    BIND(?sarObj AS ?sar)
  }

  OPTIONAL {
    ?monitoring kyc:monitoringCustomer ?customer ;
                kyc:hasAlert ?alertObj .
    BIND(?alertObj AS ?alert)
  }
}

# ============================================================
# Query 11: Enhanced Due Diligence Requirements
# ============================================================
SELECT ?customerID ?fullName ?eddReason ?eddStatus ?assignedTo
WHERE {
  ?customer kyc:customerID ?customerID ;
            kyc:fullName ?fullName ;
            kyc:hasDueDiligence ?edd .

  ?edd a kyc:EDD ;
       kyc:eddStatus ?eddStatus ;
       kyc:eddReason ?eddReason ;
       kyc:assignedTo ?assignedTo .

  FILTER(?eddStatus IN ("PENDING", "IN_PROGRESS"))
}

# ============================================================
# Query 12: Geographic Risk Distribution
# ============================================================
SELECT ?countryCode ?riskCategory (COUNT(?customer) AS ?customerCount)
WHERE {
  ?customer kyc:countryOfResidence ?countryCode ;
            kyc:hasRiskAssessment ?assessment .

  ?assessment kyc:hasRiskFactor ?geoFactor .

  ?geoFactor a kyc:GeographicRisk ;
             kyc:riskCategory ?riskCategory .
}
GROUP BY ?countryCode ?riskCategory
ORDER BY ?riskCategory DESC(?customerCount)

# ============================================================
# Query 13: Document Expiry Alert
# ============================================================
SELECT ?customerID ?fullName ?docType ?docNumber ?expiryDate ?daysUntilExpiry
WHERE {
  ?customer kyc:customerID ?customerID ;
            kyc:fullName ?fullName ;
            kyc:hasIdentityDocument ?doc .

  ?doc a ?docClass ;
       kyc:documentNumber ?docNumber ;
       kyc:documentExpiryDate ?expiryDate .

  ?docClass rdfs:subClassOf* kyc:IdentityDocument .
  BIND(STRAFTER(STR(?docClass), "#") AS ?docType)

  BIND(xsd:integer((?expiryDate - CURRENT_DATE()) / "P1D"^^xsd:duration) AS ?daysUntilExpiry)

  FILTER(?daysUntilExpiry <= 30 && ?daysUntilExpiry >= 0)
}
ORDER BY ?daysUntilExpiry

# ============================================================
# Query 14: False Positive Analysis
# ============================================================
SELECT ?ruleName (COUNT(?alert) AS ?totalAlerts)
       (SUM(?isFalsePositive) AS ?falsePositives)
       ((?falsePositives / ?totalAlerts * 100) AS ?falsePositiveRate)
WHERE {
  ?alert kyc:triggeredByRule ?rule ;
         a ?alertClass .

  ?rule kyc:ruleName ?ruleName .

  BIND(IF(?alertClass = kyc:FalsePositive, 1, 0) AS ?isFalsePositive)
}
GROUP BY ?ruleName
HAVING (?falsePositiveRate > 50)
ORDER BY DESC(?falsePositiveRate)

# ============================================================
# Query 15: Customer Onboarding Status
# ============================================================
SELECT ?customerID ?fullName ?onboardingStage ?completionPercent ?blockers
WHERE {
  ?customer kyc:customerID ?customerID ;
            kyc:fullName ?fullName ;
            kyc:onboardingStage ?onboardingStage ;
            kyc:onboardingProgress ?progress .

  ?progress kyc:completionPercent ?completionPercent .

  OPTIONAL {
    ?progress kyc:hasBlocker ?blocker .
    BIND(GROUP_CONCAT(?blocker; separator=", ") AS ?blockers)
  }

  FILTER(?completionPercent < 100)
}
ORDER BY ?completionPercent
