import express from 'express';

import { Client, cacheExchange, fetchExchange, gql } from '@urql/core';
import { EpisodeResponse } from './types';
import { transformEpisode, transformEpisodeList } from './mappings';

const app = express();
const PORT = 3000;

const root = "https://social.audiothek.de/@blaue-couch"


const audiothekApi = new Client({
	url: 'https://api.ardaudiothek.de/graphql',
	exchanges: [cacheExchange, fetchExchange],
});

const query = gql`
	query Item {
		item(id: "14278953") {
			show {
				coreId
				externalId
				title
				url
				publisher: publicationService {
					coreId
					dvbServiceId
					title
					url
					organizationName
					organization {
						name
						url
					}
				}
				coreDocument
			}
			assetId
			url: sharingUrl
			title
			description
			published: publishDate
			updated: core(key: "modified")
			imagesList {
				url
				title
			}
			coreDocument
			audioList {
				title
				audioCodec
				href
			}
		}
	}
`;

async function fetchData<R>(query: any, variables: any) {
	const result = await audiothekApi.query<R>(query, variables).toPromise();
	if (result.error) {
		throw result.error;
	}
	// console.log(JSON.stringify(result.data, null, 2));
	return result.data;
}



async function main() {
	const response = await fetchData<EpisodeResponse>(query, { id: '14278953' });

	if (response) {
		const activityPubEpisode = transformEpisode(response);
		console.log(JSON.stringify(activityPubEpisode, null, 2));
	}
}

// main();


app.get('/:actor/episodes/:id', async (req, res) => {

	try {
		const data = await fetchData<EpisodeResponse>(query, { id: req.params.id });
		if (!data) {
			res.status(404).json({ error: 'Episode not found' });
			return;
		}

		// TODO: verifiy that the actor is the same as the attributedTo field

		const activityPubDocument = transformEpisode(data);
		res.json(activityPubDocument);
	} catch (error) {
		res.status(500).json({ error: 'Failed to fetch episode data' });
	}
});

app.get('/:actor/episodes', async (req, res) => {
	const offset = 10 * ((+req.query.page! || 1) - 1);

	const query = gql`
	query ShowWithEpisodes($showId: ID!, $first: Int = 10, $offset: Int) {
 show(id: $showId) {
					coreId
				externalId
				title
				url

				items(first: $first, orderBy: PUBLISH_DATE_DESC, offset: $offset, condition:  {
					 isPublished: true
				}) {
					nodes {
						assetId
						title
						url: sharingUrl
					}
				}
				publisher: publicationService {
					coreId
					dvbServiceId
					title
					url
					organizationName
					organization {
						name
						url
					}
				}
			}
		}
	`;


	try {

		// TODO: verifiy that the actor is the same as the attributedTo field


		const data = await fetchData<any>(query, { showId: "urn:ard:show:a42d1ea0b4a07053", offset });
		if (!data) {
			res.status(404).json({ error: 'Episode not found' });
			return;
		}


		const activityPubDocument = transformEpisodeList(data);
		res.json(activityPubDocument);
	} catch (error) {
		res.status(500).json({ error: 'Failed to fetch episode data' });
	}
});

app.get('/:actor/outbox', async (req, res) => {
	const query = gql`
	query ShowEpisodeTotal($showId: ID!) {
  show(id: $showId) {
    coreId
    externalId
    title
    url

    items(condition: { isPublished: true }) {
      totalCount
    }
  }
}`;


	const data = await fetchData<any>(query, { showId: "urn:ard:show:a42d1ea0b4a07053" });
	if (!data) {
		res.status(404).json({ error: 'Show not found' });
		return;
	}

	const { totalCount } = data.show.items;

	res.json({
		"@context": "https://www.w3.org/ns/activitystreams",
		"id": `${root}/outbox`,
		"type": "OrderedCollection",
		"to": [
			"https://www.w3.org/ns/activitystreams#Public"
		],
		"totalItems": totalCount,
		"first": `${root}/episodes?page=1`,
		"current": `${root}/outbox`,
		"last": `${root}/episodes?page=${Math.floor(totalCount/10)}`
	});
});

app.get('/:actor', async (req, res) => {
	res.json({
		"@context": "https://www.w3.org/ns/activitystreams",
		"id": "urn:ard:show:a42d1ea0b4a07053",
		"type": "Service",
		"name": "Blaue Couch",
		"externalId": "https://feeds.br.de/blaue-couch/feed.xml",
		"attributedTo": "urn:ard:publisher:c4a9cee041835529",
		"publisher": {
			"type": "BroadcastService",
			"name": "BAYERN 1",
			"url": "https://www.ardaudiothek.de/radio/br/bayern-1/",
			"organization": {
				"type": "Organization",
				"name": "BR",
				"url": "https://www.ardaudiothek.de/radio/br/"
			}
		}
	});
});

app.get('/', (req, res) => res.redirect('/@blaue-couch'));

app.listen(PORT, () => {
	console.log(`Server running at http://localhost:${PORT}`);
});