package model

import (
	"context"
	"database/sql"
	"fmt"

	pb "code.hackerspace.pl/hscloud/bgpwtf/cccampix/proto"
	"github.com/golang/glog"
	"github.com/jmoiron/sqlx"
)

func (m *sqlModel) RecordPeeringDBPeerRouters(ctx context.Context, members []*pb.PeeringDBMember) error {
	tx := m.db.MustBeginTx(ctx, &sql.TxOptions{})
	defer tx.Rollback()

	for _, member := range members {
		// Get existing routers for peer.
		q := `
			SELECT peer_routers.id, peer_routers.v4, peer_routers.v6
			FROM peer_routers
			LEFT JOIN peers ON (peer_routers.peer_id = peers.id)
			WHERE peer_routers.source = 'from-peeringdb'
			  AND peers.asn = ?
		`
		q = tx.Rebind(q)
		existing := []sqlPeerRouter{}
		if err := tx.SelectContext(ctx, &existing, q, fmt.Sprintf("%d", member.Asn)); err != nil {
			return fmt.Errorf("SELECT peerRouters: %v", err)
		}

		// Find all routers that need to be deleted because they're outdated.
		// We do not attempt updates, only removals/recreations.

		// UUID -> bool
		toDelete := make(map[string]bool)

		for _, ex := range existing {
			// Try to find a requested router with same IP addresses.
			found := false
			for _, router := range member.Routers {
				if router.Ipv4 == ex.V4.String && router.Ipv6 == ex.V6.String {
					found = true
					break
				}
			}

			// Not found, mark for deletion.
			if !found {
				toDelete[ex.ID] = true
			}
		}

		// Find all routers that need to be created.
		toAdd := []sqlPeerRouter{}
		for _, router := range member.Routers {
			// Try to find an existing router with same IP addresses.
			found := false
			for _, ex := range existing {
				if router.Ipv4 == ex.V4.String && router.Ipv6 == ex.V6.String {
					found = true
					break
				}
			}
			// Not found, mark for creation.
			if !found {
				ta := sqlPeerRouter{
					Source: "from-peeringdb",
					ASN:    fmt.Sprintf("%d", member.Asn),
				}
				if router.Ipv6 != "" {
					ta.V6.String = router.Ipv6
					ta.V6.Valid = true
				}
				if router.Ipv4 != "" {
					ta.V4.String = router.Ipv4
					ta.V4.Valid = true
				}
				toAdd = append(toAdd, ta)
			}
		}

		if len(toDelete) > 0 {
			glog.Infof("RecordPeeringDBPeers: deleting %v", toDelete)
		}
		if len(toAdd) > 0 {
			glog.Infof("RecordPeeringDBPeers: adding %+v", toAdd)
		}

		// Delete any routers, if needed.
		if len(toDelete) > 0 {
			// Get list of IDs to delete.
			deleteIds := make([]string, len(toDelete))
			i := 0
			for id, _ := range toDelete {
				deleteIds[i] = id
				i += 1
			}
			query, args, err := sqlx.In("DELETE FROM peer_Routers WHERE id IN (?)", deleteIds)
			if err != nil {
				return fmt.Errorf("DELETE peerRouters: %v", err)
			}
			query = tx.Rebind(query)
			_, err = tx.ExecContext(ctx, query, args...)
			if err != nil {
				return fmt.Errorf("DELETE peerRouters: %v", err)
			}
		}

		// Add any routers, if needed.
		for _, ta := range toAdd {
			q := `
				INSERT INTO peer_routers
					(peer_id, v6, v4, source)
				SELECT
					peers.id, :v6, :v4, :source
				FROM
					peers
				WHERE peers.asn = :asn
			`
			if _, err := tx.NamedExecContext(ctx, q, ta); err != nil {
				return fmt.Errorf("INSERT peerRouters: %v", err)
			}
		}
	}

	return tx.Commit()
}
