{
  "$schema": "http://json-schema.org/draft-07/schema#",
  "$id": "https://opensourcemed.info/schemas/permaculture-site-design.schema.json",
  "title": "Permaculture Site & Design Element Schema (Alberta-first)",
  "description": "Normalized schema joining terrain/hydrology/soil/climate site attributes with permaculture design-element placement logic. Designed to share site-level fields with the companion crop-suitability (EcoCrop-based) schema so both can query the same underlying site record.",
  "type": "object",
  "required": ["site_id", "location", "terrain", "design_elements"],
  "properties": {
    "site_id": {
      "type": "string",
      "description": "Stable unique identifier for the site/parcel."
    },
    "site_name": { "type": "string" },
    "location": {
      "type": "object",
      "required": ["latitude", "longitude"],
      "properties": {
        "latitude": { "type": "number" },
        "longitude": { "type": "number" },
        "elevation_m": { "type": "number" },
        "legal_land_description": {
          "type": "object",
          "description": "Alberta Township System (ATS) description, used to cross-reference Alberta government open data (soil, wetland, elevation datasets are frequently indexed by ATS/section).",
          "properties": {
            "quarter_section": { "type": "string" },
            "section": { "type": "integer" },
            "township": { "type": "integer" },
            "range": { "type": "integer" },
            "meridian": { "type": "integer" }
          }
        },
        "municipality": { "type": "string" },
        "nearest_town": { "type": "string" }
      }
    },
    "terrain": {
      "type": "object",
      "required": ["slope_percent", "aspect"],
      "properties": {
        "slope_percent": {
          "type": "number",
          "description": "Derived from a Digital Elevation Model (DEM). Alberta source: Alberta Elevation LiDAR-derived DEM (Alberta Open Government Portal); coarser national fallback: Canadian Digital Elevation Model (CDEM), Natural Resources Canada."
        },
        "aspect": {
          "type": "string",
          "enum": ["N", "NE", "E", "SE", "S", "SW", "W", "NW", "flat"],
          "description": "Compass direction slope faces; derived from same DEM source as slope_percent."
        },
        "landform_position": {
          "type": "string",
          "enum": ["ridge", "upper_slope", "mid_slope", "lower_slope", "valley_floor", "floodplain", "depression", "flat_upland"],
          "description": "Position in the local catena; used to locate keyline keypoints and swale feasibility."
        },
        "keypoint_present": {
          "type": "boolean",
          "description": "True if a keyline keypoint (slope inflection from convex to concave) is identifiable from contour/DEM analysis on this parcel."
        },
        "erosion_risk": {
          "type": "string",
          "enum": ["low", "moderate", "high"],
          "description": "Can be modeled from slope, soil erodibility factor (K-factor), and cover; Alberta source: Agricultural Region of Alberta Soil Inventory Database (AGRASID) erosion risk layers."
        }
      }
    },
    "hydrology": {
      "type": "object",
      "properties": {
        "annual_precipitation_mm": {
          "type": "number",
          "description": "Source: ECCC Canadian Climate Normals (1991-2020), nearest station or gridded product."
        },
        "seasonal_distribution": {
          "type": "string",
          "enum": ["even", "summer_peak", "winter_peak", "erratic"],
          "description": "Relevant to swale/pond sizing; Alberta precipitation is strongly summer-peaked (convective storms May-Aug)."
        },
        "distance_to_nearest_watercourse_m": { "type": "number" },
        "watershed": {
          "type": "string",
          "description": "Source: Alberta River Basins mapping / Alberta Environment and Parks; also HYDAT (Water Survey of Canada) for gauged streams."
        },
        "wetland_class": {
          "type": ["string", "null"],
          "description": "Source: Alberta Merged Wetland Inventory (AMWI). Presence of a class III/IV/V wetland restricts swale/pond siting and triggers regulatory review under the Alberta Water Act."
        },
        "water_table_depth_m": {
          "type": ["number", "null"],
          "description": "Source: Alberta Water Well Information Database (existing well logs) where available; otherwise estimated from landform position."
        },
        "flood_risk_zone": {
          "type": "boolean",
          "description": "Source: Alberta Flood Hazard Mapping Program."
        }
      }
    },
    "soil": {
      "type": "object",
      "properties": {
        "soil_series": {
          "type": "string",
          "description": "Source: AGRASID (Agricultural Region of Alberta Soil Inventory Database), Alberta Agriculture and Irrigation."
        },
        "texture": {
          "type": "string",
          "enum": ["sand", "loamy_sand", "sandy_loam", "loam", "silt_loam", "clay_loam", "clay", "organic"]
        },
        "drainage_class": {
          "type": "string",
          "enum": ["rapid", "well", "moderately_well", "imperfect", "poor", "very_poor"]
        },
        "depth_to_bedrock_cm": { "type": ["number", "null"] },
        "cli_agricultural_capability_class": {
          "type": "string",
          "description": "1-7 class + subclass, source: Canada Land Inventory (CLI) soil capability for agriculture, Agriculture and Agri-Food Canada.",
          "enum": ["1", "2", "3", "4", "5", "6", "7"]
        },
        "organic_matter_percent": { "type": ["number", "null"] },
        "ph": { "type": ["number", "null"] }
      }
    },
    "climate": {
      "type": "object",
      "properties": {
        "plant_hardiness_zone": {
          "type": "string",
          "description": "Source: Natural Resources Canada Plant Hardiness Zones (2014 update). Most of central/southern Alberta falls 2b-4a; foothills and northern Alberta colder."
        },
        "frost_free_days": {
          "type": "number",
          "description": "Source: ECCC Canadian Climate Normals, nearest station."
        },
        "growing_degree_days_base5": { "type": "number" },
        "prevailing_wind_direction": {
          "type": "string",
          "enum": ["N", "NE", "E", "SE", "S", "SW", "W", "NW"],
          "description": "Alberta: predominantly W/NW, with damaging chinook and winter northerlies; drives windbreak sector placement."
        },
        "chinook_exposure": {
          "type": "boolean",
          "description": "Relevant along the Alberta foothills corridor; causes damaging freeze-thaw cycling that affects perennial/woody plant selection independent of hardiness zone."
        }
      }
    },
    "existing_vegetation": {
      "type": "object",
      "properties": {
        "cover_type": {
          "type": "string",
          "enum": ["bare_disturbed", "annual_cropland", "tame_pasture", "native_grassland", "shrubland", "deciduous_forest", "coniferous_forest", "mixedwood_forest", "wetland_vegetation"],
          "description": "Source: Alberta Biodiversity Monitoring Institute (ABMI) land cover product, or AAFC Annual Crop Inventory for cropland history."
        },
        "successional_stage": {
          "type": "string",
          "enum": ["pioneer", "early_successional", "mid_successional", "climax"]
        }
      }
    },
    "proximity_context": {
      "type": "object",
      "description": "Distance/context fields for the property relative to water, settlements, amenities, and reported crime. Distances computed from the site centroid or boundary (implementation choice) to the nearest feature of each type.",
      "properties": {
        "nearest_water_source": {
          "type": "object",
          "description": "Nearest surface water feature usable as a water source, distinct from the on-site hydrology block (which describes the site itself). Source: same Alberta hydrography/Wet Areas Mapping ArcGIS REST endpoints already used for the hydrology block, queried for nearest-feature rather than intersects.",
          "properties": {
            "distance_m": { "type": "number" },
            "feature_type": {
              "type": "string",
              "enum": ["river", "stream", "lake", "pond", "wetland"]
            },
            "feature_name": { "type": ["string", "null"] }
          }
        },
        "nearest_city": {
          "type": "object",
          "description": "Nearest StatCan-defined population centre / incorporated city. Source: Statistics Canada Population Centres (POPCTR) boundary file, or Alberta municipal boundary layer (AltaLIS/geodiscover) for the named polygon + centroid.",
          "properties": {
            "name": { "type": "string" },
            "distance_km": { "type": "number" },
            "population": { "type": ["integer", "null"] }
          }
        },
        "nearest_settlement": {
          "type": "object",
          "description": "Nearest named place regardless of size (hamlet, village, town, summer village) — distinct from nearest_city since Alberta has many small unincorporated hamlets that matter for local supply/services. Source: GeoNames Canada or Statistics Canada Geographic Attribute File, cross-checked against Alberta's Specialized and Rural Municipality hamlet lists.",
          "properties": {
            "name": { "type": "string" },
            "distance_km": { "type": "number" },
            "settlement_type": {
              "type": "string",
              "enum": ["hamlet", "village", "town", "summer_village", "city", "indian_reserve", "unincorporated"]
            }
          }
        },
        "amenities": {
          "type": "array",
          "description": "Nearest instance of each amenity category. Source: OpenStreetMap via Overpass API (free, no key required) or Google Places API (better POI completeness/freshness, requires billing).",
          "items": {
            "type": "object",
            "properties": {
              "category": {
                "type": "string",
                "enum": ["grocery", "hardware_store", "hospital", "clinic", "fuel_station", "school", "veterinary", "feed_farm_supply", "fire_station", "police_detachment"]
              },
              "name": { "type": "string" },
              "distance_km": { "type": "number" }
            }
          }
        },
        "crime_risk": {
          "type": "object",
          "description": "Jurisdiction-level crime context, NOT a point-level estimate — Canadian crime statistics are published by police service/detachment area, so this reflects the reporting jurisdiction the site falls within, not the specific parcel. Source: Statistics Canada Table 35-10-0177-01 (incident-based crime statistics by police service) and the annual Crime Severity Index; jurisdiction boundary via RCMP detachment area or municipal police service boundary where published.",
          "properties": {
            "reporting_jurisdiction": { "type": "string" },
            "crime_severity_index": { "type": ["number", "null"] },
            "rural_or_urban_classification": {
              "type": "string",
              "enum": ["rural", "urban"],
              "description": "Rural Alberta has consistently reported higher crime rates than urban Alberta in StatCan's rural-urban comparisons, so this classification alone is a meaningful coarse signal."
            },
            "data_year": { "type": "integer" }
          }
        }
      }
    },
    "predicted_well_depth": {
      "type": "object",
      "description": "Estimated aquifer completion depth and static water level from subsurface hydrology (nearby pump-test SWL, screen intervals, water-bearing lithology IDW) — NOT the min–max of total drilled depths and NOT topography alone. Bedrock thickness and Wet Areas Mapping depth-to-water are covariates. See design-rules-and-data-sources.md Section 3.",
      "properties": {
        "estimated_depth_m": {
          "type": ["number", "null"],
          "description": "Recommended aquifer completion depth (m below ground surface), IDW of screen bottoms / wet zones / SWL+interval."
        },
        "estimated_depth_range_m": {
          "type": "object",
          "description": "Confidence band around the hydrology-based completion depth (scatter of local aquifer targets), not raw drilled min–max.",
          "properties": {
            "low_m": { "type": "number" },
            "high_m": { "type": "number" }
          }
        },
        "estimated_static_water_level_m": { "type": ["number", "null"] },
        "estimated_aquifer_top_m": {
          "type": ["number", "null"],
          "description": "Estimated top of productive zone (m bgs) from wet lithology or SWL."
        },
        "target_hydrostratigraphic_unit": {
          "type": ["string", "null"],
          "description": "Named aquifer/formation the estimate assumes, where AGS hydrostratigraphic mapping resolves one for the area."
        },
        "nearby_well_count": {
          "type": "integer",
          "description": "Number of existing well records used in the interpolation, within the search radius — the primary signal for how much to trust the estimate."
        },
        "nearby_well_search_radius_km": { "type": "number" },
        "confidence": {
          "type": "string",
          "enum": ["well_control_dense", "well_control_sparse", "no_nearby_wells_bedrock_model_only"],
          "description": "well_control_dense/sparse = interpolated from actual nearby well logs; no_nearby_wells_bedrock_model_only = fell back to the regional AGS bedrock topography grid alone, lowest confidence."
        },
        "hydrology_basis": {
          "type": "array",
          "items": { "type": "string" },
          "description": "Human-readable list of hydrology signals used (SWL IDW, screens, wet lithology, WAM DTW, etc.)."
        },
        "disclaimer_required": {
          "type": "boolean",
          "default": true,
          "description": "UI must always present this as an estimate with a recommendation to consult a local licensed driller, never as a guaranteed depth."
        }
      }
    },
    "land_value": {
      "type": "object",
      "description": "Informational valuation context only — does NOT feed swale/keyline/guild suitability scoring. Assessed or transfer-aggregate values, never free bulk sale transactions (Alberta Land Titles is pay-per-lookup).",
      "properties": {
        "assessed_land_value": {
          "type": ["number", "null"],
          "description": "Parcel-level assessed land value (CAD) where separable; otherwise null or derived from rural CLI aggregate × acreage."
        },
        "land_value_per_acre": {
          "type": ["number", "null"],
          "description": "assessed_land_value / parcel_acreage, or rural CLI $/acre (optionally FCC-adjusted)."
        },
        "land_value_data_year": {
          "type": ["integer", "null"]
        },
        "land_value_source": {
          "type": "string",
          "enum": ["municipal_assessment", "cli_municipality_aggregate", "none"]
        },
        "nearby_land_value_sample_n": {
          "type": "integer",
          "description": "Number of nearby assessed parcels used for the neighbourhood distribution."
        },
        "nearby_land_value_search_radius_m": {
          "type": ["number", "null"],
          "description": "Actual search radius used after expanding 800m → 1.5 → 3 → 5 → 10 → 15 km until n_min or cap."
        }
      }
    },
    "design_elements": {
      "type": "array",
      "description": "Recommended/placed design moieties for this site, generated by applying the if-then ruleset below to the terrain/hydrology/soil/climate fields above. Each element is value-framed (primary_value, value_headline) for the Expanding Edge recommendation engine.",
      "items": {
        "type": "object",
        "required": ["element_type", "condition_basis", "placement_notes"],
        "properties": {
          "element_type": {
            "type": "string",
            "enum": [
              "swale", "keyline_cultivation", "pond", "hugelkultur_mound",
              "windbreak", "herb_spiral", "food_forest_guild", "terrace",
              "keyhole_bed", "shelterbelt_zone", "water_harvesting_earthwork"
            ]
          },
          "condition_basis": {
            "type": "string",
            "description": "Which site attribute(s) triggered this recommendation, e.g. 'slope_percent 3-12 AND drainage_class well-to-imperfect'."
          },
          "placement_notes": { "type": "string" },
          "zone": {
            "type": "integer",
            "minimum": 1,
            "maximum": 5,
            "description": "Permaculture zone (1=nearest/most-tended, 5=wild) this element belongs in."
          },
          "confidence": {
            "type": "string",
            "enum": ["rule_based_high", "rule_based_moderate", "needs_site_visit"]
          },
          "primary_value": {
            "type": "string",
            "description": "Client-facing outcome this technique primarily delivers (water_storage, wind_protection, food_production, etc.).",
            "enum": [
              "water_storage", "water_harvest", "erosion_control", "wind_protection",
              "snow_management", "microclimate", "shade", "food_production", "medicinal",
              "soil_building", "nitrogen_fixing", "biodiversity", "beauty_access",
              "compliance_safety"
            ]
          },
          "secondary_values": {
            "type": "array",
            "items": { "type": "string" },
            "description": "Additional client outcomes (max 3)."
          },
          "value_headline": {
            "type": "string",
            "description": "One sentence outcome for this parcel (leads the recommendation card)."
          },
          "technique_label": {
            "type": "string",
            "description": "Human technique name (Contour swale, Windbreak / shelterbelt, etc.)."
          },
          "effort": {
            "type": "string",
            "enum": ["low", "medium", "high"]
          },
          "season_hint": {
            "type": ["string", "null"]
          },
          "related_services": {
            "type": "array",
            "items": { "type": "string" },
            "description": "Expanding Edge service tags for CTAs (e.g. shelterbelt_design)."
          },
          "priority": {
            "type": "integer",
            "description": "Sort rank for recommendation engine (lower = sooner). Compliance/water before food."
          }
        }
      }
    },
    "recommendations": {
      "type": "object",
      "description": "Value-first recommendation engine envelope. Eligibility stays in design_elements; this groups and ranks by client outcome.",
      "properties": {
        "summary_sentence": {
          "type": "string",
          "description": "One-line priority story for this parcel."
        },
        "priority_ordered": {
          "type": "array",
          "description": "design_elements sorted by priority (compliance → water → wind → soil → food).",
          "items": { "type": "object" }
        },
        "by_value": {
          "type": "object",
          "description": "Map of primary_value id → array of design elements delivering that outcome.",
          "additionalProperties": {
            "type": "array",
            "items": { "type": "object" }
          }
        },
        "value_counts": {
          "type": "array",
          "description": "Primary values present with counts for filter chips (sorted by engine priority).",
          "items": {
            "type": "object",
            "properties": {
              "id": { "type": "string" },
              "label": { "type": "string" },
              "count": { "type": "integer" },
              "min_priority": { "type": "integer" }
            }
          }
        },
        "related_services": {
          "type": "array",
          "description": "Expanding Edge service CTAs implied by this recommendation set.",
          "items": {
            "type": "object",
            "properties": {
              "id": { "type": "string" },
              "label": { "type": "string" },
              "blurb": { "type": "string" },
              "href": { "type": "string", "format": "uri" },
              "cta": { "type": "string" },
              "hit_count": { "type": "integer" },
              "best_priority": { "type": "integer" }
            }
          }
        }
      }
    },

    "data_provenance": {
      "type": "array",
      "description": "Track which datasets populated this record, for auditability and re-run when sources update.",
      "items": {
        "type": "object",
        "properties": {
          "field": { "type": "string" },
          "source_name": { "type": "string" },
          "source_date": { "type": "string", "format": "date" },
          "source_url": { "type": "string", "format": "uri" }
        }
      }
    }
  }
}
