<?xml version="1.0" encoding="UTF-8"?>
<xs:schema xmlns:xs="http://www.w3.org/2001/XMLSchema" elementFormDefault="qualified">

  <!-- ============================================================ -->
  <!-- Common types (inlined from custom-report-common.xsd)         -->
  <!-- ============================================================ -->

  <xs:simpleType name="nonEmptyTrimmedString">
    <xs:restriction base="xs:string">
      <xs:minLength value="1"/>
    </xs:restriction>
  </xs:simpleType>

  <xs:simpleType name="reportIdentifierType">
    <xs:restriction base="xs:string">
      <xs:minLength value="1"/>
    </xs:restriction>
  </xs:simpleType>

  <xs:simpleType name="runtimeValueNameType">
    <xs:restriction base="xs:string">
      <xs:minLength value="1"/>
    </xs:restriction>
  </xs:simpleType>

  <xs:simpleType name="yyyymmddType">
    <xs:restriction base="xs:string">
      <xs:pattern value="\d{8}"/>
    </xs:restriction>
  </xs:simpleType>

  <xs:simpleType name="codedEntryValueType">
    <xs:restriction base="xs:string">
      <xs:enumeration value="activityDate"/>
      <xs:enumeration value="activity"/>
      <xs:enumeration value="codeDescription"/>
      <xs:enumeration value="activityTime"/>
      <xs:enumeration value="activityEndDate"/>
      <xs:enumeration value="activityStatus"/>
      <xs:enumeration value="value"/>
      <xs:enumeration value="bodySite"/>
      <xs:enumeration value="route"/>
      <xs:enumeration value="batchNumber"/>
      <xs:enumeration value="expiryDate"/>
      <xs:enumeration value="responsiblePractitioner"/>
      <xs:enumeration value="responsiblePractitionerIdentifier"/>
      <xs:enumeration value="responsibleOrganizationOdsCode"/>
      <xs:enumeration value="activityPerformedHere"/>
      <xs:enumeration value="responsibleOrganisation"/>
      <xs:enumeration value="encounterType"/>
      <xs:enumeration value="encounterTypeCode"/>
    </xs:restriction>
  </xs:simpleType>

  <xs:simpleType name="demographicInformationValueType">
    <xs:restriction base="xs:string">
      <xs:enumeration value="patientName"/>
      <xs:enumeration value="patientPrimaryIdentifier"/>
      <xs:enumeration value="patientUuid"/>
      <xs:enumeration value="patientNhsNumber"/>
      <xs:enumeration value="patientDateOfBirth"/>
      <xs:enumeration value="patientAge"/>
      <xs:enumeration value="patientGender"/>
      <xs:enumeration value="patientRegistrationType"/>
      <xs:enumeration value="patientRegistrationDate"/>
      <xs:enumeration value="patientCurrentRegistrationType"/>
      <xs:enumeration value="namedGP"/>
      <xs:enumeration value="homeAddress"/>
      <xs:enumeration value="homePhoneNumber"/>
      <xs:enumeration value="mobilePhoneNumber"/>
      <xs:enumeration value="emailAddress"/>
      <xs:enumeration value="currentRegistrationStartDate"/>
      <xs:enumeration value="dateOfDeath"/>
      <xs:enumeration value="prescriptionsDispensedByPractice"/>
      <xs:enumeration value="careHomeResident"/>
    </xs:restriction>
  </xs:simpleType>

  <xs:complexType name="runtimeValueType">
    <xs:simpleContent>
      <xs:extension base="xs:string">
        <xs:attribute name="name" type="runtimeValueNameType" use="required"/>
      </xs:extension>
    </xs:simpleContent>
  </xs:complexType>

  <xs:complexType name="patientQueryRuntimeValueType">
    <xs:sequence>
      <xs:element name="runtimeValue" type="runtimeValueType" minOccurs="1" maxOccurs="unbounded"/>
    </xs:sequence>
    <xs:attribute name="name" type="runtimeValueNameType" use="required"/>
  </xs:complexType>

  <xs:complexType name="patientQueryRuntimeValuesType">
    <xs:sequence>
      <xs:element name="patientQueryRuntimeValue" type="patientQueryRuntimeValueType" minOccurs="1" maxOccurs="unbounded"/>
    </xs:sequence>
  </xs:complexType>

  <xs:complexType name="demographicInformationColumnType">
    <xs:attribute name="value" type="demographicInformationValueType" use="required"/>
    <xs:attribute name="headerName" type="xs:string" use="optional"/>
  </xs:complexType>

  <xs:complexType name="codedEntryValueColumnType">
    <xs:attribute name="value" type="codedEntryValueType" use="required"/>
    <xs:attribute name="headerName" type="xs:string" use="optional"/>
  </xs:complexType>

  <xs:complexType name="anyElementType" mixed="true">
    <xs:sequence>
      <xs:any minOccurs="0" maxOccurs="unbounded" processContents="skip"/>
    </xs:sequence>
    <xs:anyAttribute processContents="skip"/>
  </xs:complexType>

  <xs:complexType name="dateColumnType" mixed="true">
    <xs:sequence>
      <xs:any minOccurs="0" maxOccurs="unbounded" processContents="skip"/>
    </xs:sequence>
    <xs:attribute name="headerName" type="xs:string" use="optional"/>
    <xs:attribute name="useAsFilter" type="xs:string" use="optional"/>
  </xs:complexType>

  <xs:complexType name="derivedValueColumnType" mixed="true">
    <xs:sequence>
      <xs:any minOccurs="0" maxOccurs="unbounded" processContents="skip"/>
    </xs:sequence>
    <xs:attribute name="headerName" type="xs:string" use="optional"/>
    <xs:attribute name="useAsFilter" type="xs:string" use="optional"/>
    <xs:attribute name="basePatientQuery" type="xs:string" use="optional"/>
  </xs:complexType>

  <xs:complexType name="valueColumnType" mixed="true">
    <xs:sequence>
      <xs:any minOccurs="0" maxOccurs="unbounded" processContents="skip"/>
    </xs:sequence>
    <xs:attribute name="headerName" type="xs:string" use="optional"/>
  </xs:complexType>

  <xs:complexType name="columnsType">
    <xs:choice minOccurs="1" maxOccurs="unbounded">
      <xs:element name="demographicInformationColumn" type="demographicInformationColumnType"/>
      <xs:element name="codedEntryValueColumn" type="codedEntryValueColumnType"/>
      <xs:element name="dateColumn" type="dateColumnType"/>
      <xs:element name="derivedValueColumn" type="derivedValueColumnType"/>
      <xs:element name="valueColumn" type="valueColumnType"/>
    </xs:choice>
  </xs:complexType>

  <!-- rowsType: exactly one <patientQuery> -->
  <xs:complexType name="rowsType">
    <xs:sequence>
      <xs:element name="patientQuery" type="inlinePatientQueryType"/>
    </xs:sequence>
  </xs:complexType>

  <!-- inlinePatientQueryType: full query -->
  <xs:complexType name="inlinePatientQueryType">
    <xs:sequence>
      <xs:element name="name"        type="xs:string"   minOccurs="0"/>
      <xs:element name="description" type="xs:string"   minOccurs="0"/>
      <xs:element name="population"  type="populationType"/>
      <xs:element name="codeLists"   type="codeListsType"/>
      <xs:element name="variables"   type="variablesType"/>
      <xs:element name="rules"       type="rulesType"/>
    </xs:sequence>
  </xs:complexType>

  <!-- populationType: one of four population sources -->
  <xs:complexType name="populationType">
    <xs:choice>
      <xs:element name="patientQueryReference"  type="nonEmptyTrimmedString"/>
      <xs:element name="patientQuery"           type="embeddedPatientQueryType"/>
      <xs:element name="patientReportReference" type="nonEmptyTrimmedString"/>
      <xs:element name="patientIdList"          type="patientIdListType"/>
    </xs:choice>
  </xs:complexType>

  <!-- embeddedPatientQueryType: recursive inline patient query (no schemaVersion attribute) -->
  <xs:complexType name="embeddedPatientQueryType">
    <xs:sequence>
      <xs:element name="name"        type="xs:string"   minOccurs="0"/>
      <xs:element name="description" type="xs:string"   minOccurs="0"/>
      <xs:element name="population"  type="populationType"/>
      <xs:element name="codeLists"   type="codeListsType"/>
      <xs:element name="variables"   type="variablesType"/>
      <xs:element name="rules"       type="rulesType"/>
    </xs:sequence>
  </xs:complexType>

  <!-- patientIdListType: one or more patient UUIDs -->
  <xs:complexType name="patientIdListType">
    <xs:sequence>
      <xs:element name="patientId" type="nonEmptyTrimmedString" minOccurs="1" maxOccurs="unbounded"/>
    </xs:sequence>
  </xs:complexType>

  <!-- variablesType: zero or more variable declarations -->
  <xs:complexType name="variablesType">
    <xs:choice minOccurs="0" maxOccurs="unbounded">
      <xs:element name="fixedDate"               type="fixedDateVariableType"/>
      <xs:element name="codedEntryVariable"      type="codedEntryDateVariableType"/>
      <xs:element name="derivedFixedDate"        type="derivedFixedDateType"/>
      <xs:element name="patientAge"              type="namedVariableType"/>
      <xs:element name="patientEntryDate"        type="namedVariableType"/>
      <xs:element name="patientClinicalSex"      type="namedVariableType"/>
      <xs:element name="patientRegistrationType" type="namedVariableType"/>
      <xs:element name="patientNamedGp"          type="namedVariableType"/>
    </xs:choice>
  </xs:complexType>

  <!-- namedVariableType: attribute-only variable element -->
  <xs:complexType name="namedVariableType">
    <xs:anyAttribute processContents="skip"/>
  </xs:complexType>

  <xs:complexType name="fixedDateVariableType">
    <xs:simpleContent>
      <xs:extension base="xs:string">
        <xs:attribute name="name"         type="nonEmptyTrimmedString" use="required"/>
        <xs:attribute name="runtimeValue" type="xs:string"             use="optional"/>
      </xs:extension>
    </xs:simpleContent>
  </xs:complexType>

  <xs:complexType name="codedEntryDateVariableType">
    <xs:attribute name="name"   type="nonEmptyTrimmedString" use="required"/>
    <xs:attribute name="code"   type="nonEmptyTrimmedString" use="required"/>
    <xs:attribute name="select" use="required"/>
    <xs:attribute name="order"  use="required"/>
    <xs:attribute name="take"   use="required">
      <xs:simpleType>
        <xs:restriction base="xs:string">
          <xs:enumeration value="latest"/>
          <xs:enumeration value="earliest"/>
          <xs:enumeration value="all"/>
        </xs:restriction>
      </xs:simpleType>
    </xs:attribute>
    <xs:attribute name="value1"                        type="xs:string" use="optional"/>
    <xs:attribute name="value2"                        type="xs:string" use="optional"/>
    <xs:attribute name="performedAtLocalOrganisation"  type="xs:string" use="optional"/>
    <xs:attribute name="clinicallyRelevantDate"        type="xs:string" use="optional"/>
  </xs:complexType>

  <xs:complexType name="derivedFixedDateType">
    <xs:attribute name="name"          type="nonEmptyTrimmedString" use="required"/>
    <xs:attribute name="fixedDateName" type="nonEmptyTrimmedString" use="required"/>
    <xs:attribute name="operation"     type="nonEmptyTrimmedString" use="required"/>
  </xs:complexType>

  <!-- codeListsType: zero or more code list entries -->
  <xs:complexType name="codeListsType">
    <xs:sequence>
      <xs:element name="codeList" type="codeListEntryType" minOccurs="0" maxOccurs="unbounded"/>
    </xs:sequence>
  </xs:complexType>

  <!-- codeListEntryType: wrapper containing <name> and one of three payload types -->
  <xs:complexType name="codeListEntryType">
    <xs:sequence>
      <xs:element name="name" type="nonEmptyTrimmedString"/>
      <xs:choice>
        <xs:element name="codeListReference"  type="nonEmptyTrimmedString"/>
        <xs:element name="codeListDefinition" type="codeListDefinitionBodyType"/>
        <xs:element name="fixedCodeList"      type="fixedCodeListType"/>
      </xs:choice>
    </xs:sequence>
  </xs:complexType>

  <xs:complexType name="codeListDefinitionBodyType">
    <xs:sequence>
      <xs:element name="rules" type="codeListRulesType"/>
    </xs:sequence>
  </xs:complexType>

  <xs:complexType name="fixedCodeListType">
    <xs:sequence>
      <xs:element name="codes">
        <xs:complexType>
          <xs:sequence>
            <xs:element name="code" type="nonEmptyTrimmedString" minOccurs="1" maxOccurs="unbounded"/>
          </xs:sequence>
        </xs:complexType>
      </xs:element>
    </xs:sequence>
  </xs:complexType>

  <xs:complexType name="codeListRulesType">
    <xs:choice minOccurs="1" maxOccurs="unbounded">
      <xs:element name="inclusion" type="nonEmptyTrimmedString"/>
      <xs:element name="exclusion" type="nonEmptyTrimmedString"/>
    </xs:choice>
  </xs:complexType>

  <!-- rulesType / ruleType: one or more if/then/else rules -->
  <xs:complexType name="rulesType">
    <xs:sequence>
      <xs:element name="rule" type="ruleType" minOccurs="1" maxOccurs="unbounded"/>
    </xs:sequence>
  </xs:complexType>

  <xs:complexType name="ruleType">
    <xs:sequence>
      <xs:element name="if"   type="ruleExpressionType"/>
      <xs:element name="then" type="thenValueType"/>
      <xs:element name="else" type="elseValueType"/>
    </xs:sequence>
  </xs:complexType>

  <!-- ruleExpressionType: must not end with whitespace -->
  <xs:simpleType name="ruleExpressionType">
    <xs:restriction base="xs:string">
      <xs:minLength value="1"/>
      <xs:pattern value=".*\S"/>
    </xs:restriction>
  </xs:simpleType>

  <xs:simpleType name="thenValueType">
    <xs:restriction base="xs:string">
      <xs:enumeration value="next-rule"/>
      <xs:enumeration value="select"/>
    </xs:restriction>
  </xs:simpleType>

  <xs:simpleType name="elseValueType">
    <xs:restriction base="xs:string">
      <xs:enumeration value="reject"/>
    </xs:restriction>
  </xs:simpleType>

  <!-- ============================================================ -->
  <!-- Root elements                                                 -->
  <!-- ============================================================ -->

  <!-- Verify root of activity report has required tags/attributes -->
  <xs:element name="activityReport">
    <xs:complexType>
      <xs:sequence>
        <xs:element name="name"    type="nonEmptyTrimmedString"/>
        <xs:element name="rows"    type="rowsType"/>
        <xs:element name="columns" type="columnsType"/>
      </xs:sequence>
      <xs:attribute name="schemaVersion" use="required">
        <xs:simpleType>
          <xs:restriction base="xs:integer">
            <xs:enumeration value="2"/>
          </xs:restriction>
        </xs:simpleType>
      </xs:attribute>
    </xs:complexType>
  </xs:element>

  <!-- Verify root of patient report has required tags/attributes -->
  <xs:element name="patientReport">
    <xs:complexType>
      <xs:sequence>
        <xs:element name="name"    type="nonEmptyTrimmedString"/>
        <xs:element name="rows"    type="rowsType"/>
        <xs:element name="columns" type="columnsType"/>
      </xs:sequence>
      <xs:attribute name="schemaVersion" use="required">
        <xs:simpleType>
          <xs:restriction base="xs:integer">
            <xs:enumeration value="2"/>
          </xs:restriction>
        </xs:simpleType>
      </xs:attribute>
    </xs:complexType>
  </xs:element>

</xs:schema>
