# ChargedDevice Entity

Reprezentarea unui dispozitiv care se încarcă prin meter.

## Responsabilități

- Modelarea unui dispozitiv (iPhone, Watch, Charger, Powerbank, Other)
- Gestionarea sesiunilor de încărcare
- Colectarea de măsurători durante sesiune
- Calculul integrității şi detectării conflictelor

## Invarianţi

- **MUST**: Fiecare ChargedDevice are un `id` (UUID) unic
- **MUST**: O sesiune de încărcare are timestamp-uri valide: `startTime <= currentTime <= endTime`
- **MUST**: Măsurătorile într-o sesiune sunt ordonate cronologic
- **MUST**: O sesiune activă pe un dispozitiv trebuie să aibă un singur Meter asociat
- **MUST**: Energia calculată (Wh) trebuie să fie ne-negativă
- **SHOULD**: Un device cu 0 măsurători ar trebui marcat pentru curatare pe CloudKit
- **MAY**: Duplicate sessions pe același MAC pot fi mergate după detectare

## API Public

### Proprietăţi

| Proprietate | Tip | Descriere | Observaţii |
|---|---|---|---|
| `id` | UUID | Identificator unic | Generat la creare |
| `deviceName` | String | Nume ales de utilizator | De ex: "My iPhone 15" |
| `deviceClass` | ChargedDeviceClass | Tip: iPhone, Watch, Charger, Powerbank, Other | |
| `kind` | ChargedDeviceKind | Device sau Charger | Derivat din `deviceClass` |
| `createdAt` | Date | Data creării | Immutable |
| `chargeRecords` | [ChargeRecord] | Lista sesiunilor de încărcare | Sorted by startTime |
| `totalEnergy` | Double | Total Wh consumat/furnizat | Calculat din sesiuni |
| `lastChargedAt` | Date? | Data ultimei sesiuni | Nullable |

### Metode

```swift
// Gestionare sesiuni
func startSession(meter: Meter) -> ChargeRecord
// MUST: sessionID este UUID unic
// MUST: startTime = now()
// MUST: retur ChargeRecord cu status "active"

func recordMeasurement(_ measurement: Measurement, in session: ChargeRecord)
// MUST: measurement.timestamp > session.startTime
// SHOULD: measure-urile sunt colectate la ~1Hz
// MUST: nu merge dacă sesiunea e finalizată

func endSession(_ record: ChargeRecord)
// MUST: endTime = now()
// MUST: calculează total energy din măsurători
// MUST: marchez sesiunea ca "completed"

func recalculateTotalEnergy()
// Recalculează sum-ul de Wh din toate sesiunile
// SHOULD: se apelează după conflict resolution

// Naming
func renameToDevice(_ newName: String)
// MUST: actualizează proprietatea şi persistă

// Conflict handling
func mergeWith(_ other: ChargedDevice, keepingRecords: Bool = true)
// MUST: combină sessions de pe ambele device-uri
// MUST: remove-ă duplicates după MAC address
// SHOULD: logs merge operation pentru debug
```

## Comportamente critice

### Sesiuni de încărcare

- **MUST**: Doar o singură sesiune per device poate fi activă la orice moment
- **MUST**: Sesiunile completate sunt imutable
- **SHOULD**: Sesiunile care durează > 24h sunt marcate cu warning
- **MAY**: Sesiuni orphaned (meter deconectat > 1h) pot fi finalizate automat

### Calculul energiei

- **MUST**: Energia = ∑(V * A * Δt) pentru fiecare interval
- **MUST**: Unitatea trebuie să fie Wh (Watt-hours)
- **SHOULD**: Energia negativă în sesiune = problema în măsurători, loghează warning

### Conflict detection și rezoluție

Se declanşează când:
1. Două sesiuni cu aceeași categorie de device în same time window
2. Două sesiuni pe aceeași meter cu overlap temporal

Rezoluţie:
- **MUST**: Sesiunea cu mai multe măsurători = "winner"
- **MUST**: Energiile sunt combinate (∑)
- **SHOULD**: Old session data este archived (Core Data snapshot)
- **MAY**: Notifică utilizator despre merge

### State management

- **MUST**: Active session nu poate fi schimbat în mod normal (read-only)
- **MUST**: State tranzițion: idle → active → completed (nu poate reveni)
- **SHOULD**: Completed sesiuni sunt persistent în Core Data

## Testare

### Unit tests

```swift
// Sesiuni
test_startSessionCreatesValidRecord()
test_endSessionCalculatesEnergy()
test_activeSessions_CanOnlyBeOne()
test_sessionTimeValidation()

// Măsurători
test_recordMeasurementFailsIfSessionEnded()
test_measurementsAreOrdered()
test_emptySessionsCalculateZeroEnergy()

// Conflict
test_mergeDetectsDuplicateSessions()
test_mergeKeepsMoreCompleteMeasurements()
test_mergeRecalculates_TotalEnergy()

// Naming
test_renameUpdatesPersistence()
```

### Integration tests

- [ ] Device apare în Charged Devices list după start sesiune
- [ ] Sesiuni complete salvate în Core Data
- [ ] CloudKit sync nu pierde sesiuni
- [ ] Energiile sunt consistente după conflict merge
- [ ] Device name e persistent

## Dependenţe

- `Meter`: conectare şi măsurători
- `ChargeInsightsStore`: persistență sesiuni
- `CloudKitSync`: replicare iCloud

## Notes

Documentaţie asoc:
- [Charge Session Integrity](../Charge%20Session%20Integrity%20and%20Conflict%20Healing.md)
- [No Ampere-Hours in UI](../No%20Ampere-Hours%20in%20UI%20or%20Model.md)
