<style scoped>
body {
	background-color: #f8f9fa;
	min-height: 100vh;
	display: flex;
	flex-direction: column;
}

body > .container-fluid {
	flex: 1;
}

.progress-bar {
	background-color: #0d6efd;
	transition: width 0.3s ease;
}
</style>
<template>
	<template v-if="district">
		<router-view v-slot="{ Component }">
			<LoadingOverlay
				:is-loading="isLoading"
				loading-text="Loading previous data"
			>
				<component
					:is="Component"
					:district="district"
					@doAddress="doAddress"
					@doEvidence="doEvidence"
					@doContact="doContact"
					@doPermission="doPermission"
					v-model="compliance"
				/>
			</LoadingOverlay>
		</router-view>
	</template>
	<template v-else>
		<p>loading {{ slug }}...</p>
	</template>
</template>

<script setup lang="ts">
import { computed, onMounted, ref } from "vue";
import { computedAsync } from "@vueuse/core";

import type { Image } from "@/components/ImageUpload.vue";
import { useStoreDistrict } from "@/rmo/store/district";
import { useStoreLocal } from "@/store/local";
import { useStoreLocation } from "@/store/location";
import Intro from "@/rmo/content/compliance/Intro.vue";
import LoadingOverlay from "@/components/LoadingOverlay.vue";
import type { District, PublicReport } from "@/type/api";
import { Address, Location, PermissionAccess } from "@/type/api";
import { type Contact } from "@/rmo/content/compliance/Contact.vue";
import { type Permission } from "@/rmo/content/compliance/Permission.vue";

export interface Compliance {
	address: Address;
	comments: string;
	contact: Contact;
	id: string;
	images: Image[];
	location: Location;
	permission: Permission;
	uri: string;
}
interface ComplianceUpdate {
	address?: Address;
	comments?: string;
	contact?: Contact;
	//id: string;
	//images?: Image[];
	location?: Location;
	permission?: Permission;
	//uri: string;
}
interface Props {
	slug: string;
}

const districtStore = useStoreDistrict();

const compliance = ref<Compliance>({
	address: new Address(),
	comments: "",
	contact: {
		name: "",
		phone: "",
		can_text: true,
		email: "",
	},
	id: "",
	images: [],
	location: {
		latitude: 0,
		longitude: 0,
	},
	permission: {
		access: PermissionAccess.UNSELECTED,
		access_instructions: "",
		availability_notes: "",
		gate_code: "",
		has_dog: false,
		wants_scheduled: false,
	},
	uri: "",
});
const isLoading = ref<boolean>(true);
const isUploading = ref<boolean>(false);
const props = defineProps<Props>();
const report = ref<PublicReport | null>();
const district = computedAsync(async (): Promise<District | undefined> => {
	const districts = await districtStore.list();
	return districts.find((district: District) => district.slug == props.slug);
});
const storeLocal = useStoreLocal();
const storeLocation = useStoreLocation();
async function createReport(client_id: string, loc?: GeolocationPosition) {
	const formData = new FormData();
	formData.append("client_id", client_id);
	if (loc) {
		formData.append("location.accuracy", loc.coords.accuracy.toString());
		formData.append("location.latitude", loc.coords.latitude.toString());
		formData.append("location.longitude", loc.coords.longitude.toString());
	} else {
		formData.append("location.accuracy", "0");
		formData.append("location.latitude", "0");
		formData.append("longitude", "0");
	}
	const resp = await fetch("/api/rmo/compliance", {
		method: "POST",
		body: formData,
		// Don't set Content-Type, the borwser should do it
	});
	if (!resp.ok) {
		const content = await resp.text();
		console.error("Failed to create compliance report", resp.status, content);
		return;
	}
	const body = await resp.json();
	storeLocal.setExistingComplianceReportURI(body.uri);
	compliance.value.uri = body.uri;
}
function doAddress() {
	console.log("address done", compliance.value.address);
	updateReport({
		address: compliance.value.address,
	});
}
function doEvidence() {
	uploadImages(compliance.value.images);
}
function doContact() {
	console.log("contact", compliance.value.contact);
}
function doPermission() {
	console.log("permission", compliance.value.permission);
}
async function fetchExistingReport(report_uri: string) {
	isLoading.value = true;
	const resp = await fetch(report_uri);
	if (!resp.ok) {
		isLoading.value = false;
		const content = await resp.text();
		console.error(
			"Failed to fetch existing report",
			report_uri,
			resp.status,
			content,
		);
		return;
	}
	const body = await resp.json();
	compliance.value.id = body.id;
	compliance.value.uri = body.uri;
	compliance.value.address = body.address;
	isLoading.value = false;
}
async function updateReport(updates: ComplianceUpdate) {
	if (!compliance.value.uri) {
		console.log("Refusing to update report without URI");
		return;
	}
	const resp = await fetch(compliance.value.uri, {
		method: "PUT",
		body: JSON.stringify(updates),
		headers: {
			"Content-Type": "application/json",
		},
	});
	if (!resp.ok) {
		const content = await resp.text();
		console.error("Failed to update compliance", resp.status, content);
		return;
	}
}
async function uploadImages(images: Image[]) {
	isUploading.value = true;
	const formData = new FormData();
	images.map(async (image, index) => {
		formData.append(`image[${index}]`, image.file, image.name);
	});
	const url = `${compliance.value.uri}/image`;
	const response = await fetch(url, {
		body: formData,
		method: "POST",
	});
	if (!response.ok) {
		const content = await response.text();
		console.error(
			"Failed to POST images",
			url,
			response.status,
			response.statusText,
			content,
		);
		isUploading.value = false;
		return;
	}
	isUploading.value = false;
}
onMounted(() => {
	const client_id = storeLocal.getClientID();
	const report_uri = storeLocal.getExistingComplianceReportURI();
	if (report_uri) {
		fetchExistingReport(report_uri);
	} else {
		isLoading.value = false;
		createReport(client_id);
	}
	storeLocation
		.get()
		.then((loc: GeolocationPosition) => {
			compliance.value.location = loc.coords;
			updateReport({
				location: compliance.value.location,
			});
		})
		.catch((e) => {
			console.log("failed to get location", e);
		});
});
</script>
