package de.assecutor.votianlt.model;

import com.fasterxml.jackson.annotation.JsonGetter;
import com.fasterxml.jackson.annotation.JsonIgnore;
import lombok.Data;
import org.bson.types.ObjectId;
import org.springframework.data.annotation.Id;
import org.springframework.data.mongodb.core.mapping.Document;
import org.springframework.data.mongodb.core.mapping.Field;

import java.time.LocalDate;
import java.time.LocalDateTime;
import java.time.LocalTime;
import java.math.BigDecimal;
import java.util.ArrayList;
import java.util.List;
import java.util.stream.Collectors;

@Data
@Document(collection = "jobs")
public class Job {
    @Id
    @JsonIgnore
    private ObjectId id;

    // Metadaten
    @Field("job_number")
    private String jobNumber; // Eindeutige Auftragsnummer

    @Field("status")
    private JobStatus status = JobStatus.CREATED; // Status des Auftrags

    @Field("created_at")
    private LocalDateTime createdAt;

    @Field("updated_at")
    private LocalDateTime updatedAt;

    @Field("created_by")
    private String createdBy; // Benutzer, der den Auftrag erstellt hat

    @Field("is_draft")
    private boolean isDraft = false; // Kennzeichnet Entwürfe

    // Auftraggeber/Rechnungsempfänger
    @Field("customer_selection")
    private String customerSelection; // Kunde01 | KOTVor K01Nach

    // Abholadresse
    @Field("pickup_company")
    private String pickupCompany;

    @Field("pickup_salutation")
    private String pickupSalutation;

    @Field("pickup_first_name")
    private String pickupFirstName;

    @Field("pickup_last_name")
    private String pickupLastName;

    @Field("pickup_phone")
    private String pickupPhone;

    @Field("pickup_street")
    private String pickupStreet;

    @Field("pickup_house_number")
    private String pickupHouseNumber;

    @Field("pickup_address_addition")
    private String pickupAddressAddition;

    @Field("pickup_zip")
    private String pickupZip;

    @Field("pickup_city")
    private String pickupCity;

    // Lieferadresse
    @Field("delivery_company")
    private String deliveryCompany;

    @Field("delivery_salutation")
    private String deliverySalutation;

    @Field("delivery_first_name")
    private String deliveryFirstName;

    @Field("delivery_last_name")
    private String deliveryLastName;

    @Field("delivery_phone")
    private String deliveryPhone;

    @Field("delivery_street")
    private String deliveryStreet;

    @Field("delivery_house_number")
    private String deliveryHouseNumber;

    @Field("delivery_address_addition")
    private String deliveryAddressAddition;

    @Field("delivery_zip")
    private String deliveryZip;

    @Field("delivery_city")
    private String deliveryCity;

    // Digitale Abwicklung per App
    @Field("digital_processing")
    private boolean digitalProcessing;

    @Field("app_user")
    private String appUser;

    // Termine
    @Field("pickup_date")
    private LocalDate pickupDate;

    @Field("pickup_time")
    private LocalTime pickupTime;

    @Field("delivery_date")
    private LocalDate deliveryDate;

    @Field("delivery_time")
    private LocalTime deliveryTime;

    // Bemerkung
    @Field("remark")
    private String remark;

    // Preis (netto)
    @Field("price")
    private BigDecimal price;

    // Gefahrene Kilometer für Rechnungsstellung
    @Field("kilometers_driven")
    private Integer kilometersDriven;

    // Arbeitszeit in 15-Minuten-Einheiten für Rechnungsstellung
    @Field("time_in_15min_units")
    private Integer timeIn15MinUnits;

    // Service-IDs für die Rechnung
    @Field("service_ids")
    private List<String> serviceIds;

    // Ausgewählte Leistungen inkl. zugeordneter Lieferstation und Berechnungsbasis
    @Field("selected_services")
    private List<JobServiceSelection> selectedServices = new ArrayList<>();

    // Streckeninformation für die Rechnung (in km)
    @Field("route_distance_km")
    private Double routeDistanceKm;

    // Fahrtzeit in Sekunden für die Rechnung
    @Field("route_duration_seconds")
    private Integer routeDurationSeconds;

    // Referenz auf die erstellte Rechnung
    @Field("invoice_id")
    private String invoiceId;

    // Lieferstationen (bis zu 25)
    @Field("delivery_stations")
    private List<DeliveryStation> deliveryStations = new ArrayList<>();

    /**
     * Returns the ObjectId as string for JSON serialization. This ensures that the
     * job id is returned as a string when jobs are retrieved via API.
     */
    @JsonGetter("id")
    public String getIdAsString() {
        return id != null ? id.toString() : null;
    }

    /**
     * Returns the first delivery station's city. Falls back to the flat
     * deliveryCity field for backward compatibility with old jobs.
     */
    public String getFirstDeliveryCity() {
        if (deliveryStations != null && !deliveryStations.isEmpty()) {
            return deliveryStations.get(0).getCity();
        }
        return deliveryCity;
    }

    /**
     * Returns the last delivery station's city for route display.
     */
    public String getLastDeliveryCity() {
        if (deliveryStations != null && !deliveryStations.isEmpty()) {
            return deliveryStations.get(deliveryStations.size() - 1).getCity();
        }
        return deliveryCity;
    }

    /**
     * Returns all delivery cities joined with arrows for display (e.g. "Berlin →
     * Dresden → München").
     */
    public String getDeliveryCitiesDisplay() {
        if (deliveryStations != null && !deliveryStations.isEmpty()) {
            return deliveryStations.stream().map(DeliveryStation::getCity).filter(c -> c != null && !c.isBlank())
                    .collect(Collectors.joining(" \u2192 "));
        }
        return deliveryCity;
    }

    /**
     * Populates the flat delivery fields from the first delivery station for
     * backward compatibility. Call this before saving when using delivery stations.
     */
    public void syncFlatDeliveryFieldsFromStations() {
        if (deliveryStations != null && !deliveryStations.isEmpty()) {
            DeliveryStation first = deliveryStations.get(0);
            this.deliveryCompany = first.getCompany();
            this.deliverySalutation = first.getSalutation();
            this.deliveryFirstName = first.getFirstName();
            this.deliveryLastName = first.getLastName();
            this.deliveryPhone = first.getPhone();
            this.deliveryStreet = first.getStreet();
            this.deliveryHouseNumber = first.getHouseNumber();
            this.deliveryAddressAddition = first.getAddressAddition();
            this.deliveryZip = first.getZip();
            this.deliveryCity = first.getCity();
            this.deliveryDate = first.getDeliveryDate();
            this.deliveryTime = first.getDeliveryTime();
        }
    }
}
