# Tunisia GeoJSON Database Import Guide

## ✅ What Was Implemented

You now have a complete system to store Tunisia's districts and governorates in your PostgreSQL/PostGIS database instead of loading GeoJSON files in the frontend.

### Backend (Spring Boot)

1. **GeoJsonImportService.java** - Service to import GeoJSON data from `tunisia_adm1.geojson`
   - Reads the GeoJSON file from `src/main/resources/static/tunisia_adm1.geojson`
   - Creates 1 country (Tunisia)
   - Creates 5 districts (NE, NW, C, SE, SW)
   - Creates ~24 governorates with their geometries
   - Assigns each governorate to its parent district

2. **New API Endpoints in locationController.java**:
   - `POST /api/locations/tunisia/import?mapId={id}` - Import data once
   - `POST /api/locations/tunisia/reimport?mapId={id}` - Force reimport (deletes existing)
   - `GET /api/locations/map/{mapId}/districts` - Get all districts with geometries
   - `GET /api/locations/map/{mapId}/governorates` - Get all governorates with geometries
   - `GET /api/locations/district/{districtId}/governorates` - Get governorates for a district

### Frontend (Angular)

1. **locations.service.ts** - New methods:
   - `importTunisiaData(mapId)` - Trigger import
   - `reimportTunisiaData(mapId)` - Force reimport
   - `getDistricts(mapId)` - Fetch districts
   - `getGovernorates(mapId)` - Fetch governorates
   - `getGovernoratesByDistrict(districtId)` - Fetch governorates for a district

## 🚀 How to Use

### Step 1: Import Data Into Database

**Option A: Using Postman/curl**
```bash
# Import Tunisia data (first time only)
POST http://localhost:8080/api/locations/tunisia/import?mapId=1

# Force reimport (if you need to reset)
POST http://localhost:8080/api/locations/tunisia/reimport?mapId=1
```

**Option B: Add Import Button to Your App**

Add this to your component (e.g., map-settings.component.ts):

```typescript
importTunisiaData() {
  const mapId = this.currentMap?.id;
  if (!mapId) {
    alert('Please select a map first');
    return;
  }

  this.locationsService.importTunisiaData(mapId).subscribe(
    result => {
      console.log(result);
      alert(result); // Shows success message with counts
      this.loadLocations(); // Reload to see new data
    },
    error => {
      console.error('Import failed:', error);
      alert('Import failed: ' + error.message);
    }
  );
}
```

And in your HTML:
```html
<button (click)="importTunisiaData()" class="btn-import">
  Import Tunisia Data
</button>
```

### Step 2: Fetch and Display Data

**In your cesium-map component or map-settings component:**

```typescript
loadTunisiaDataFromDatabase() {
  const mapId = this.currentMap?.id;
  if (!mapId) return;

  // Get all districts
  this.locationsService.getDistricts(mapId).subscribe(districts => {
    console.log('Districts from DB:', districts);
    
    // Each district has:
    // - id, name, geometry, category='DISTRICT', type='ZONE'
    
    districts.forEach(district => {
      // Render district polygon on Cesium map
      this.renderDistrictOnMap(district);
      
      // Get governorates for this district
      this.locationsService.getGovernoratesByDistrict(district.id!).subscribe(governorates => {
        console.log(`Governorates in ${district.name}:`, governorates);
        
        governorates.forEach(gov => {
          // Render governorate polygon on Cesium map
          this.renderGovernorateOnMap(gov, district);
        });
      });
    });
  });
}

renderDistrictOnMap(district: LocationDTO) {
  if (!district.geometry) return;
  
  const geojson = {
    type: 'Feature',
    properties: { name: district.name, category: 'DISTRICT' },
    geometry: {
      type: district.geometry.type,
      coordinates: district.geometry.coordinates
    }
  };

  // Load with Cesium
  Cesium.GeoJsonDataSource.load(geojson, {
    stroke: Cesium.Color.CYAN,
    fill: Cesium.Color.CYAN.withAlpha(0.2),
    strokeWidth: 3
  }).then(dataSource => {
    this.viewer.dataSources.add(dataSource);
  });
}

renderGovernorateOnMap(governorate: LocationDTO, district: LocationDTO) {
  if (!governorate.geometry) return;
  
  const geojson = {
    type: 'Feature',
    properties: { 
      name: governorate.name, 
      category: 'GOVERNORATE',
      districtName: district.name
    },
    geometry: {
      type: governorate.geometry.type,
      coordinates: governorate.geometry.coordinates
    }
  };

  const color = this.getDistrictColor(district.name);
  
  Cesium.GeoJsonDataSource.load(geojson, {
    stroke: color,
    fill: color.withAlpha(0.3),
    strokeWidth: 2
  }).then(dataSource => {
    this.viewer.dataSources.add(dataSource);
    
    // Add click handler
    dataSource.entities.values[0].properties = {
      isGovernorate: true,
      governorateId: governorate.id,
      governorateName: governorate.name,
      districtId: district.id
    };
  });
}
```

### Step 3: Replace Existing GeoJSON Loading

**OLD CODE (Delete this):**
```typescript
//❌ Remove this - loading GeoJSON from frontend
this.http.get('/assets/tunisia_adm1.geojson').subscribe(data => {
  // Process GeoJSON locally
});
```

**NEW CODE (Use this):**
```typescript
// ✅ Load from database
loadTunisiaDataFromDatabase(); // Call the method above
```

## 📊 Database Structure

After import, your `locations` table will contain:

```sql
-- 1 Country
id | name    | category | type    | parent_id | geometry
1  | Tunisia | COUNTRY  | COUNTRY | NULL      | NULL

-- 5 Districts
id | name       | category | type | parent_id | geometry
2  | North East | DISTRICT | ZONE | 1         | NULL
3  | North West | DISTRICT | ZONE | 1         | NULL
4  | Center     | DISTRICT | ZONE | 1         | NULL
5  | South East | DISTRICT | ZONE | 1         | NULL
6  | South West | DISTRICT | ZONE | 1         | NULL

-- ~24 Governorates
id | name      | category     | type | parent_id | geometry
7  | Tunis     | GOVERNORATE  | ZONE | 2         | <MultiPolygon>
8  | Ariana    | GOVERNORATE  | ZONE | 2         | <MultiPolygon>
9  | Ben Arous | GOVERNORATE  | ZONE | 2         | <MultiPolygon>
... (more governorates)
```

## 🎯 District-Governorate Mapping

The import service uses this mapping:

```typescript
NE (North East): Ben Arous, Tunis, Ariana, Manouba, Zaghouan, Nabeul, Bizerte
NW (North West): Jendouba, Kef, Siliana, Béja
C (Center): Sousse, Monastir, Mahdia, Kairouan, Kasserine, Sidi Bouzid
SE (South East): Sfax, Gabès, Médenine, Tataouine
SW (South West): Gafsa, Tozeur, Kebili
```

## 🔄 Benefits of Database Storage

1. **Performance** - No need to load large GeoJSON files on frontend
2. **Flexibility** - Can update geometries/names via API
3. **Add Content** - Can attach images, text, links to districts/governorates
4. **Relationships** - Parent-child relationships maintained in DB
5. **Scalability** - Can add more regions/countries easily

## 🧪 Testing the Import

1. Start your backend: `mvn spring-boot:run`
2. Use Postman to import:
   ```
   POST http://localhost:8080/api/locations/tunisia/import?mapId=1
   ```
3. Check response: Should say "Import successful! Created: 1 country, 5 districts, 24 governorates"
4. Verify in database:
   ```sql
   SELECT count(*) FROM locations WHERE category = 'GOVERNORATE';
   SELECT count(*) FROM locations WHERE category = 'DISTRICT';
   ```

## 🎨 Next Steps

1. **Import the data** using the endpoint
2. **Remove GeoJSON loading** from your Angular components
3. **Replace with database calls** using the new service methods
4. **Add edit/content features** - Users can now add images/text to districts/governorates
5. **Optimize rendering** - Load only visible governorates based on zoom level

## ⚠️ Important Notes

- Make sure `tunisia_adm1.geojson` is in `Back/src/main/resources/static/`
- Import is idempotent - won't duplicate if run multiple times
- Use `/reimport` endpoint to force refresh if geometry data changes
- All geometries are stored as PostGIS geometry types (Polygon/MultiPolygon)
- SRID is 4326 (WGS84 - standard for lat/lon)

---

**You're all set!** Your Tunisia map data is now database-driven instead of file-driven. 🚀
