<?php

namespace App\Console\Commands\Debug;

use Illuminate\Console\Command;
use Illuminate\Database\QueryException;
use Illuminate\Support\Facades\DB;

use App\Models\{Address,System};

class AddressMerge extends Command
{
	/**
	 * The name and signature of the console command.
	 *
	 * @var string
	 */
	protected $signature = 'debug:address:merge'
		.' {src : Source Address}'
		.' {dst : Destination Address}'
		.' {--F|force : Force}'
		.' {--I|ignore : Ignore different BBSes}'
		.' {--d|dryrun : Dry Run}';

	/**
	 * The console command description.
	 *
	 * @var string
	 */
	protected $description = 'Permanently remove a duplicate address';

	/**
	 * Execute the console command.
	 *
	 * @return int
	 */
	public function handle(): int
	{
		$src = Address::withTrashed()->findOrfail($this->argument('src'));
		$dst = Address::withTrashed()->findOrfail($this->argument('dst'));

		if ((! $this->option('ignore')) && ($src->system_id !== $dst->system_id) && ($src->system->name !== System::default)) {
			$this->error(sprintf('FTN addresses are from different systems (%s/%s)',$src->system->name,$dst->system->name));

			return self::FAILURE;
		}

		if ((! $this->option('force')) && ($src->ftn !== $dst->ftn)) {
			$this->error(sprintf('FTN addresses are not the same (%s:%s)',$src->ftn,$dst->ftn));

			return self::FAILURE;
		}

		if ($src->active) {
			$this->error(sprintf('Source [%s] is still active',$src->ftn));

			return self::FAILURE;
		}

		DB::beginTransaction();

		// Find all echomail seenbys
		$x = DB::update('UPDATE echomail_seenby SET address_id=? WHERE address_id=?',[$dst->id,$src->id]);
		$this->info(sprintf('Updated [%d] echomail seenby records',$x));

		// Find all echomail paths
		$x = DB::update('UPDATE echomail_path SET address_id=? WHERE address_id=?',[$dst->id,$src->id]);
		$this->info(sprintf('Updated [%d] echomail path records',$x));

		// Find all echomails
		$x = DB::update('UPDATE echomails SET fftn_id=? WHERE fftn_id=?',[$dst->id,$src->id]);
		$this->info(sprintf('Updated [%d] echomail source records',$x));

		// Find all netmails
		$x = DB::update('UPDATE netmails SET fftn_id=? WHERE fftn_id=?',[$dst->id,$src->id]);
		$this->info(sprintf('Updated [%d] netmail source records',$x));

		// Find all netmails
		$x = DB::update('UPDATE netmails SET tftn_id=? WHERE tftn_id=?',[$dst->id,$src->id]);
		$this->info(sprintf('Updated [%d] netmail destination records',$x));

		// Find all nodelist
		$x = DB::update('UPDATE address_nodelist SET address_id=? WHERE address_id=?',[$dst->id,$src->id]);
		$this->info(sprintf('Updated [%d] nodelist records',$x));

		// Find all file seenbys
		$x = DB::update('UPDATE file_seenby SET address_id=? WHERE address_id=?',[$dst->id,$src->id]);
		$this->info(sprintf('Updated [%d] file seenby records',$x));

		// Find all files
		$x = DB::update('UPDATE files SET fftn_id=? WHERE fftn_id=?',[$dst->id,$src->id]);
		$this->info(sprintf('Updated [%d] file source records',$x));

		// Resubscribe echoareas
		try {
			$x = DB::update('UPDATE address_echoarea SET address_id=? WHERE address_id=?',[$dst->id,$src->id]);

		} catch (QueryException $e) {
			DB::rollback();
			$this->error(sprintf('You may need to remove %s:%s (%d) from echoareas',$src->ftn,$src->system->name,$src->id));

			return self::FAILURE;
		}

		$this->info(sprintf('Updated [%d] echomail subscription records',$x));

		// Resubscribe fileareas
		try {
			$x = DB::update('UPDATE address_filearea SET address_id=? WHERE address_id=?',[$dst->id,$src->id]);
		} catch (QueryException $e) {
			DB::rollback();
			$this->error(sprintf('You may need to remove %s:%s (%d) from fileareas',$src->ftn,$src->system->name,$src->id));

			return self::FAILURE;
		}

		$this->info(sprintf('Updated [%d] filearea subscription records',$x));

		if ($this->option('dryrun')) {
			$this->warn(sprintf('NOT deleting [%s] - DRY RUN',$src->ftn));
			DB::rollBack();

		} else {
			if ($src->forceDelete()) {
				$this->alert(sprintf('%s deleted.',$src->ftn));
				DB::commit();

			} else {
				$this->warn(sprintf('Address [%s] didnt delete?',$src->ftn));
				DB::rollBack();
			}
		}

		return self::SUCCESS;
	}
}