from fastapi import FastAPI
from sqlmodel import SQLModel, create_engine, Session, select
from datetime import datetime
from datastore.model import Label, LabelAssignment, Meter, Measurement
from pydantic import BaseModel

SQLITE_FILE_NAME = "database.db"
sqlite_url = f"sqlite:///{SQLITE_FILE_NAME}"

connect_args = {"check_same_thread": False}
engine = create_engine(sqlite_url, echo=True, connect_args=connect_args)


def create_db_and_tables():
    SQLModel.metadata.create_all(engine)


app = FastAPI()


@app.on_event("startup")
def on_startup():
    create_db_and_tables()


@app.get("/meters")
def read_usage():
    with Session(engine) as session:
        meters = session.query(Meter).all()
        return meters


@app.get("/meters/{meter_id}/")
def read_meter(meter_id: int):
    with Session(engine) as session:
        meter = session.query(Meter).filter(Meter.id == meter_id).first()
        return meter


@app.get("/meters/{meter_id}/measurements")
def read_measurements(meter_id: int, start_date: datetime = None, end_date: datetime = None):
    with Session(engine) as session:
        query = session.query(Measurement).filter(
            Measurement.meter_id == meter_id)
        if start_date:
            query = query.filter(Measurement.capture_time >= start_date)
        if end_date:
            query = query.filter(Measurement.capture_time <= end_date)

        measurements = query.all()
        return measurements


class LabelAssignmentPostData(BaseModel):
    label_id: int
    start_time: datetime
    end_time: datetime


@app.post("/meters/{meter_id}/labels")
def assign_label(meter_id: int, data: LabelAssignmentPostData):
    with Session(engine) as session:
        assignment = LabelAssignment(meter_id=meter_id,
                                    label_id=data.label_id,
                                    start_time=data.start_time,
                                    end_time=data.end_time)
        ass1 = LabelAssignment(meter_id=1, label_id=1, start_time=datetime(
            2020, 1, 1, 0, 0, 30), end_time=datetime(2020, 1, 1, 0, 0, 40))
        session.add(assignment)
        session.commit()
        return "Label assigned successfully!"


@app.get("/meters/{meter_id}/labels")
def get_assigned_labels(meter_id: int):
    with Session(engine) as session:
        labels = session.query(LabelAssignment.start_time, LabelAssignment.end_time, Label.name, Label.color, LabelAssignment.id).filter(
            LabelAssignment.meter_id == meter_id).join(Label).all()
        return labels


@app.delete("/labels/assignments/{assignment_id}")
def delete_assignment(assignment_id: int):
    with Session(engine) as session:
        session.query(LabelAssignment).filter(
            LabelAssignment.id == assignment_id).delete()
        session.commit()
        return "Label assignment deleted successfully!"

@app.get("/labels")
def get_labels():
    with Session(engine) as session:
        labels = session.query(Label).all()
        return labels


@app.post("/db/setDefaults")
def set_defaults():
    clear_db()
    with Session(engine) as session:
        meter1 = Meter(serial_number="Meter one", id=1)
        meter2 = Meter(serial_number="Meter two", id=2)
        for i in range(0, 59):
            session.add(Measurement(meter_id=meter1.id, voltage_phase_1=10+i,
                                    voltage_phase_2=(i*i) % 230, voltage_phase_3=30, capture_time=datetime(2020, 1, 1, 0, 0, i)))

        session.add(meter1)
        session.add(meter2)

        label1 = Label(name="Label one", id=1, color="red")
        label2 = Label(name="Label two", id=2, color="blue")
        ass1 = LabelAssignment(meter_id=meter1.id, label_id=label1.id, start_time=datetime(
            2020, 1, 1, 0, 0, 30), end_time=datetime(2020, 1, 1, 0, 0, 40))
        session.add(label1)
        session.add(label2)
        session.add(ass1)
        session.commit()
        return "Default set successfully!"


@app.post("/db/clear")
def clear_db():
    with Session(engine) as session:
        session.query(Meter).delete()
        session.query(Measurement).delete()
        session.query(Label).delete()
        session.query(LabelAssignment).delete()
        session.commit()
        return "DB cleared successfuly!"


if __name__ == "__main__":
    import os
    import uvicorn

    host = os.getenv("SMIC_HOST", "0.0.0.0")
    port = int(os.getenv("SMIC_PORT", 8081))

    uvicorn.run(app, host=host, port=port)

datastore.model.Label sqlmodel.SQLModel.metadata.create_all datetime.datetime datastore.model.Meter uvicorn.run sqlmodel.Session os.getenv fastapi.FastAPI datastore.model.LabelAssignment sqlmodel.create_engine
[((355, 418), 'sqlmodel.create_engine', 'create_engine', (['sqlite_url'], {'echo': '(True)', 'connect_args': 'connect_args'}), '(sqlite_url, echo=True, connect_args=connect_args)\n', (368, 418), False, 'from sqlmodel import SQLModel, create_engine, Session, select\n'), ((498, 507), 'fastapi.FastAPI', 'FastAPI', ([], {}), '()\n', (505, 507), False, 'from fastapi import FastAPI\n'), ((453, 489), 'sqlmodel.SQLModel.metadata.create_all', 'SQLModel.metadata.create_all', (['engine'], {}), '(engine)\n', (481, 489), False, 'from sqlmodel import SQLModel, create_engine, Session, select\n'), ((4336, 4369), 'os.getenv', 'os.getenv', (['"""SMIC_HOST"""', '"""0.0.0.0"""'], {}), "('SMIC_HOST', '0.0.0.0')\n", (4345, 4369), False, 'import os\n'), ((4420, 4458), 'uvicorn.run', 'uvicorn.run', (['app'], {'host': 'host', 'port': 'port'}), '(app, host=host, port=port)\n', (4431, 4458), False, 'import uvicorn\n'), ((629, 644), 'sqlmodel.Session', 'Session', (['engine'], {}), '(engine)\n', (636, 644), False, 'from sqlmodel import SQLModel, create_engine, Session, select\n'), ((797, 812), 'sqlmodel.Session', 'Session', (['engine'], {}), '(engine)\n', (804, 812), False, 'from sqlmodel import SQLModel, create_engine, Session, select\n'), ((1069, 1084), 'sqlmodel.Session', 'Session', (['engine'], {}), '(engine)\n', (1076, 1084), False, 'from sqlmodel import SQLModel, create_engine, Session, select\n'), ((1670, 1685), 'sqlmodel.Session', 'Session', (['engine'], {}), '(engine)\n', (1677, 1685), False, 'from sqlmodel import SQLModel, create_engine, Session, select\n'), ((1719, 1834), 'datastore.model.LabelAssignment', 'LabelAssignment', ([], {'meter_id': 'meter_id', 'label_id': 'data.label_id', 'start_time': 'data.start_time', 'end_time': 'data.end_time'}), '(meter_id=meter_id, label_id=data.label_id, start_time=data.\n    start_time, end_time=data.end_time)\n', (1734, 1834), False, 'from datastore.model import Label, LabelAssignment, Meter, Measurement\n'), ((2282, 2297), 'sqlmodel.Session', 'Session', (['engine'], {}), '(engine)\n', (2289, 2297), False, 'from sqlmodel import SQLModel, create_engine, Session, select\n'), ((2643, 2658), 'sqlmodel.Session', 'Session', (['engine'], {}), '(engine)\n', (2650, 2658), False, 'from sqlmodel import SQLModel, create_engine, Session, select\n'), ((2905, 2920), 'sqlmodel.Session', 'Session', (['engine'], {}), '(engine)\n', (2912, 2920), False, 'from sqlmodel import SQLModel, create_engine, Session, select\n'), ((3074, 3089), 'sqlmodel.Session', 'Session', (['engine'], {}), '(engine)\n', (3081, 3089), False, 'from sqlmodel import SQLModel, create_engine, Session, select\n'), ((3119, 3157), 'datastore.model.Meter', 'Meter', ([], {'serial_number': '"""Meter one"""', 'id': '(1)'}), "(serial_number='Meter one', id=1)\n", (3124, 3157), False, 'from datastore.model import Label, LabelAssignment, Meter, Measurement\n'), ((3175, 3213), 'datastore.model.Meter', 'Meter', ([], {'serial_number': '"""Meter two"""', 'id': '(2)'}), "(serial_number='Meter two', id=2)\n", (3180, 3213), False, 'from datastore.model import Label, LabelAssignment, Meter, Measurement\n'), ((3528, 3570), 'datastore.model.Label', 'Label', ([], {'name': '"""Label one"""', 'id': '(1)', 'color': '"""red"""'}), "(name='Label one', id=1, color='red')\n", (3533, 3570), False, 'from datastore.model import Label, LabelAssignment, Meter, Measurement\n'), ((3588, 3631), 'datastore.model.Label', 'Label', ([], {'name': '"""Label two"""', 'id': '(2)', 'color': '"""blue"""'}), "(name='Label two', id=2, color='blue')\n", (3593, 3631), False, 'from datastore.model import Label, LabelAssignment, Meter, Measurement\n'), ((4000, 4015), 'sqlmodel.Session', 'Session', (['engine'], {}), '(engine)\n', (4007, 4015), False, 'from sqlmodel import SQLModel, create_engine, Session, select\n'), ((4385, 4413), 'os.getenv', 'os.getenv', (['"""SMIC_PORT"""', '(8081)'], {}), "('SMIC_PORT', 8081)\n", (4394, 4413), False, 'import os\n'), ((2004, 2034), 'datetime.datetime', 'datetime', (['(2020)', '(1)', '(1)', '(0)', '(0)', '(30)'], {}), '(2020, 1, 1, 0, 0, 30)\n', (2012, 2034), False, 'from datetime import datetime\n'), ((2058, 2088), 'datetime.datetime', 'datetime', (['(2020)', '(1)', '(1)', '(0)', '(0)', '(40)'], {}), '(2020, 1, 1, 0, 0, 40)\n', (2066, 2088), False, 'from datetime import datetime\n'), ((3714, 3744), 'datetime.datetime', 'datetime', (['(2020)', '(1)', '(1)', '(0)', '(0)', '(30)'], {}), '(2020, 1, 1, 0, 0, 30)\n', (3722, 3744), False, 'from datetime import datetime\n'), ((3768, 3798), 'datetime.datetime', 'datetime', (['(2020)', '(1)', '(1)', '(0)', '(0)', '(40)'], {}), '(2020, 1, 1, 0, 0, 40)\n', (3776, 3798), False, 'from datetime import datetime\n'), ((3421, 3450), 'datetime.datetime', 'datetime', (['(2020)', '(1)', '(1)', '(0)', '(0)', 'i'], {}), '(2020, 1, 1, 0, 0, i)\n', (3429, 3450), False, 'from datetime import datetime\n')]