#!/usr/bin/env python3
"""
SwiftShip Express — Courier website backend (Flask + SQLite).

Full mode   : python3 app.py   → serves the website AND the tracking API backed by SQLite.
Static mode : any static server (e.g. python3 -m http.server inside site/) →
              the Track page automatically falls back to site/data/tracking-fallback.json.
"""
import os
import sqlite3
import uuid
from datetime import datetime, timezone

from flask import Flask, abort, jsonify, request, send_from_directory

BASE_DIR = os.path.dirname(os.path.abspath(__file__))
SITE_DIR = os.path.join(BASE_DIR, "site")
DOWNLOADS_DIR = os.path.join(BASE_DIR, "downloads")
DB_PATH = os.path.join(BASE_DIR, "swiftship.db")

app = Flask(__name__, static_folder=SITE_DIR, static_url_path="/")

PAGES = ["index", "services", "track", "rates", "about", "contact", "downloads"]


def get_db():
    conn = sqlite3.connect(DB_PATH)
    conn.row_factory = sqlite3.Row
    return conn


def now_iso():
    return datetime.now(timezone.utc).strftime("%Y-%m-%dT%H:%M:%SZ")


# --------------------------------------------------------------------------
# Pages (static HTML lives in /site — served here and openable as plain files)
# --------------------------------------------------------------------------
def _page_handler(name):
    def handler():
        return send_from_directory(SITE_DIR, f"{name}.html")
    handler.__name__ = f"page_{name}"
    return handler


app.add_url_rule("/", "page_index", _page_handler("index"))
for _p in PAGES:
    if _p == "index":
        continue
    app.add_url_rule(f"/{_p}", f"page_{_p}", _page_handler(_p))

# clean rule for "/<page>.html" style links
@app.route("/<page_name>.html")
def page_with_suffix(page_name):
    if page_name in PAGES:
        return send_from_directory(SITE_DIR, f"{page_name}.html")
    abort(404)


# --------------------------------------------------------------------------
# Downloadable files (rate card, guides, terms, sample data export)
# --------------------------------------------------------------------------
@app.route("/downloads/<path:filename>")
def download_file(filename):
    return send_from_directory(DOWNLOADS_DIR, filename)


# --------------------------------------------------------------------------
# Tracking API — real database access
# --------------------------------------------------------------------------
@app.route("/api/track/<tracking_number>")
def api_track(tracking_number):
    number = tracking_number.strip().upper()
    conn = get_db()
    row = conn.execute(
        "SELECT * FROM shipments WHERE tracking_number = ?", (number,)
    ).fetchone()
    if row is None:
        return jsonify({
            "found": False,
            "error": (f"No shipment found for tracking number '{number}'. "
                      "Please double-check the number and try again."),
        }), 404

    events = conn.execute(
        "SELECT event_time, status, location, description "
        "FROM tracking_events WHERE shipment_id = ? ORDER BY event_time DESC",
        (row["id"],),
    ).fetchall()

    shipment = dict(row)
    shipment.pop("id", None)
    return jsonify({
        "found": True,
        "source": "database",
        "shipment": shipment,
        "events": [dict(e) for e in events],
    })


@app.route("/api/shipments")
def api_shipments():
    conn = get_db()
    rows = conn.execute(
        "SELECT tracking_number, sender_city, sender_country, recipient_city, "
        "recipient_country, service_type, weight_kg, status, current_location, "
        "estimated_delivery FROM shipments ORDER BY tracking_number"
    ).fetchall()
    return jsonify({"count": len(rows), "shipments": [dict(r) for r in rows]})


# --------------------------------------------------------------------------
# Quote + contact forms — persisted to SQLite
# --------------------------------------------------------------------------
@app.route("/api/quote", methods=["POST"])
def api_quote():
    data = request.get_json(silent=True) or {}
    missing = [f for f in ("name", "email", "origin", "destination") if not data.get(f)]
    if missing:
        return jsonify({"ok": False, "error": f"Missing required fields: {', '.join(missing)}"}), 400

    ref = f"QT-{uuid.uuid4().hex[:8].upper()}"
    conn = get_db()
    conn.execute(
        "INSERT INTO quotes (ref_number, name, email, phone, origin, destination, "
        "weight_kg, service_type, notes, created_at) VALUES (?,?,?,?,?,?,?,?,?,?)",
        (ref, data.get("name"), data.get("email"), data.get("phone") or "",
         data.get("origin"), data.get("destination"),
         float(data["weight"]) if str(data.get("weight") or "").replace(".", "").isdigit() else None,
         data.get("service") or "Standard", data.get("notes") or "", now_iso()),
    )
    conn.commit()
    conn.close()
    return jsonify({"ok": True, "reference": ref,
                    "message": "Quote request received. A SwiftShip specialist will reply within 4 business hours."})


@app.route("/api/contact", methods=["POST"])
def api_contact():
    data = request.get_json(silent=True) or {}
    missing = [f for f in ("name", "email", "message") if not data.get(f)]
    if missing:
        return jsonify({"ok": False, "error": f"Missing required fields: {', '.join(missing)}"}), 400

    ticket = f"CS-{uuid.uuid4().hex[:8].upper()}"
    conn = get_db()
    conn.execute(
        "INSERT INTO contact_messages (ticket, name, email, subject, message, created_at) "
        "VALUES (?,?,?,?,?,?)",
        (ticket, data.get("name"), data.get("email"), data.get("subject") or "General",
         data.get("message"), now_iso()),
    )
    conn.commit()
    conn.close()
    return jsonify({"ok": True, "ticket": ticket,
                    "message": "Message received. Our support team replies within 1 business day."})


@app.route("/api/health")
def api_health():
    conn = get_db()
    n = conn.execute("SELECT COUNT(*) FROM shipments").fetchone()[0]
    conn.close()
    return jsonify({"ok": True, "service": "SwiftShip Express API", "shipments_in_db": n})


if __name__ == "__main__":
    if not os.path.exists(DB_PATH):
        raise SystemExit("Database missing — run `python3 seed.py` first.")
    print("SwiftShip Express → http://localhost:8000  (Ctrl+C to stop)")
    app.run(host="0.0.0.0", port=8000, debug=False)
